Skip to content
Open
29 changes: 15 additions & 14 deletions packages/quicktype-core/src/input/JSONSchemaInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -825,13 +825,14 @@ async function addTypesInSchema(
properties: StringMap,
requiredArray: string[],
additionalProperties: unknown,
sortKey: (k: string) => number | string = (k: string): string =>
k.toLowerCase(),
sortKey?: (k: string) => number | string,
): Promise<TypeRef> {
const required = new Set(requiredArray);
const propertiesMap = mapSortBy(mapFromObject(properties), (_, k) =>
sortKey(k),
);
const unsortedPropertiesMap = mapFromObject(properties);
const propertiesMap =
sortKey === undefined
? unsortedPropertiesMap
: mapSortBy(unsortedPropertiesMap, (_, k) => sortKey(k));
const props = await mapMapSync(
propertiesMap,
async (propSchema, propName) => {
Expand Down Expand Up @@ -1164,15 +1165,15 @@ async function addTypesInSchema(
inferredAttributes,
combineProducedAttributes(({ forObject }) => forObject),
);
const order = schema.quicktypePropertyOrder
? schema.quicktypePropertyOrder
: [];
const orderKey = (propertyName: string): string => {
// use the index of the order array
const index = order.indexOf(propertyName);
// if no index then use the property name
return index !== -1 ? index : propertyName.toLowerCase();
};
const order = schema.quicktypePropertyOrder;
const orderKey = order
? (propertyName: string): string => {
// use the index of the order array
const index = order.indexOf(propertyName);
// if no index then use the property name
return index !== -1 ? index : propertyName.toLowerCase();
}
: undefined;

return await makeObject(
loc,
Expand Down
12 changes: 12 additions & 0 deletions test/fixtures/typescript/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,16 @@ const json = fs.readFileSync(sample);
const value = TopLevel.Convert.toTopLevel(json);
const backToJson = TopLevel.Convert.topLevelToJson(value);

if (sample.endsWith("property-order.1.json")) {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a shit way of testing this. The fixtures should never special-case for specific test cases!!! Find a clean way of testing this!

const input = JSON.parse(json.toString());
const output = JSON.parse(backToJson);
const keys = (object: object) => JSON.stringify(Object.keys(object));
if (
keys(input) !== keys(output) ||
keys(input.ordered) !== keys(output.ordered)
) {
throw new Error("Generated property order does not match the schema");
}
}

console.log(backToJson);
11 changes: 11 additions & 0 deletions test/inputs/schema/property-order.1.fail.no-defaults.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"zebra": "stripes",
"mango": 1.5,
"apple": true,
"delta": "change",
"ordered": {
"mango": 2.5,
"zebra": "stripes",
"apple": false
}
}
12 changes: 12 additions & 0 deletions test/inputs/schema/property-order.1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"zebra": "stripes",
"mango": 1.5,
"apple": true,
"delta": "change",
"banana": 3,
"ordered": {
"mango": 2.5,
"zebra": "stripes",
"apple": false
}
}
24 changes: 24 additions & 0 deletions test/inputs/schema/property-order.schema
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"zebra": { "type": "string" },
"mango": { "type": "number" },
"apple": { "type": "boolean" },
"delta": { "type": "string" },
"banana": { "type": "integer" },
"ordered": {
"type": "object",
"quicktypePropertyOrder": ["mango", "zebra"],
"properties": {
"zebra": { "type": "string" },
"mango": { "type": "number" },
"apple": { "type": "boolean" }
},
"required": ["zebra", "mango", "apple"],
"additionalProperties": false
}
},
"required": ["zebra", "mango", "apple", "delta", "banana", "ordered"],
"additionalProperties": false
}
3 changes: 3 additions & 0 deletions test/languages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,7 @@ export const CJSONLanguage: Language = {
/* Required properties absent are not checked (for the current implementation, can be added later, should abord parsing and return NULL) */
"ie-suffix-singularization.schema",
"intersection.schema",
"property-order.schema",
"required.schema",
// The default-value fail sample also relies on required-property
// enforcement, which cJSON does not do.
Expand Down Expand Up @@ -1935,6 +1936,7 @@ export const HaskellLanguage: Language = {
"keyword-unions.schema",
"optional-any.schema",
"ie-suffix-singularization.schema",
"property-order.schema",
"required.schema",
// The default-value fail sample also relies on required-property enforcement.
"default-value.schema",
Expand Down Expand Up @@ -2308,6 +2310,7 @@ export const ElixirLanguage: Language = {
"top-level-primitive-array.schema",
"boolean-subschema.schema",
"intersection.schema",
"property-order.schema",
"optional-any.schema",

// The test incorrectly succeeds due to the emitter being permissive for unions that contain only primitives. A future enhancement
Expand Down
Loading