diff --git a/lib/compile/jtd/serialize.ts b/lib/compile/jtd/serialize.ts index 7ebd26acb..e2e465c95 100644 --- a/lib/compile/jtd/serialize.ts +++ b/lib/compile/jtd/serialize.ts @@ -156,20 +156,20 @@ function serializeSchemaProperties(cxt: SerializeCxt, discriminator?: string): v const optProps = keys(optionalProperties) const allProps = allProperties(props.concat(optProps)) let first = !discriminator + const firstProp = gen.let("first", props.length === 0) + for (const key of props) { - serializeProperty(key, properties[key], keyValue(key)) + serializeProperty(key, properties[key], keyValue(key), false) } for (const key of optProps) { const value = keyValue(key) gen.if(and(_`${value} !== undefined`, isOwnProperty(gen, data, key)), () => - serializeProperty(key, optionalProperties[key], value) + serializeProperty(key, optionalProperties[key], value, true) ) } if (schema.additionalProperties) { gen.forIn("key", data, (key) => - gen.if(isAdditional(key, allProps), () => - serializeKeyValue(cxt, key, {}, gen.let("first", first)) - ) + gen.if(isAdditional(key, allProps), () => serializeKeyValue(cxt, key, {}, firstProp)) ) } @@ -189,9 +189,24 @@ function serializeSchemaProperties(cxt: SerializeCxt, discriminator?: string): v return gen.const("value", _`${data}${getProperty(key)}`) } - function serializeProperty(key: string, propSchema: SchemaObject, value: Name): void { - if (first) first = false - else gen.add(N.json, str`,`) + function serializeProperty( + key: string, + propSchema: SchemaObject, + value: Name, + isOptional: boolean + ): void { + if (first) { + first = false + if (isOptional) gen.assign(firstProp, false) + } else if (isOptional) { + gen.if( + firstProp, + () => gen.assign(firstProp, false), + () => gen.add(N.json, str`,`) + ) + } else { + gen.add(N.json, str`,`) + } gen.add(N.json, str`${JSON.stringify(key)}:`) serializeCode({...cxt, schema: propSchema, data: value}) } diff --git a/spec/issues/2001_jtd_only_optional_properties.spec.ts b/spec/issues/2001_jtd_only_optional_properties.spec.ts new file mode 100644 index 000000000..99cf4d5b1 --- /dev/null +++ b/spec/issues/2001_jtd_only_optional_properties.spec.ts @@ -0,0 +1,28 @@ +import _Ajv from "../ajv_jtd" +import * as assert from "assert" + +const PROP_COUNT = 3 + +describe("schema with only optional properties", () => { + let ajv: InstanceType + const schema = {optionalProperties: {}} + const data = {} + const invalidData = {} + let serialize + + before(() => { + ajv = new _Ajv() + for (let i = 0; i < PROP_COUNT; i++) { + const prop = `prop${i}` + schema.optionalProperties[prop] = {type: "uint16"} + data[prop] = i + if (i !== 0) invalidData[prop] = i + } + serialize = ajv.compileSerializer(schema) + }) + + it("should correctly compile reference to schema", () => { + assert.strictEqual(serialize(data), '{"prop0":0,"prop1":1,"prop2":2}') + assert.strictEqual(serialize(invalidData), '{"prop1":1,"prop2":2}') + }) +})