Skip to content

Add support for array of types in schema definition #78

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 23, 2018

Conversation

florianreinhart
Copy link
Contributor

Fixes #77.

This adds support for type to be an array of types, e.g.

{
    "type": "object",
    "properties": {
      "stringOrNumber": {"type": ["string", "number"]}
    }
}

Support of multiple types in tuple definitions is still missing. This probably requires some refactoring of the buildArray() function. Nevertheless, I have prepared already a test case for tuples (currently commented out).

I don't particularly like the implementation of hasArrayOfTypes(), so please let me know if you have any better ideas.

@allevo
Copy link
Member

allevo commented Feb 22, 2018

Many thanks for this PR. Can you run some benchmarks ? I like to see if there're some performance penalties between your branch and master.

@florianreinhart
Copy link
Contributor Author

Sure! I ran bench.js. Here are the results:

Before

JSON.stringify array x 4,509 ops/sec ±0.70% (92 runs sampled)
fast-json-stringify array x 8,331 ops/sec ±0.68% (92 runs sampled)
fast-json-stringify-uglified array x 8,463 ops/sec ±0.75% (90 runs sampled)
JSON.stringify long string x 17,575 ops/sec ±0.46% (97 runs sampled)
fast-json-stringify long string x 17,035 ops/sec ±1.56% (92 runs sampled)
fast-json-stringify-uglified long string x 17,522 ops/sec ±0.50% (93 runs sampled)
JSON.stringify short string x 5,653,901 ops/sec ±0.46% (94 runs sampled)
fast-json-stringify short string x 32,673,355 ops/sec ±0.38% (94 runs sampled)
fast-json-stringify-uglified short string x 33,049,197 ops/sec ±0.30% (94 runs sampled)
JSON.stringify obj x 2,126,520 ops/sec ±0.62% (96 runs sampled)
fast-json-stringify obj x 7,336,898 ops/sec ±0.95% (95 runs sampled)
fast-json-stringify-uglified obj x 7,225,950 ops/sec ±0.95% (92 runs sampled)

After

JSON.stringify array x 4,567 ops/sec ±0.47% (92 runs sampled)
fast-json-stringify array x 8,327 ops/sec ±0.77% (93 runs sampled)
fast-json-stringify-uglified array x 8,660 ops/sec ±0.64% (94 runs sampled)
JSON.stringify long string x 17,648 ops/sec ±0.43% (97 runs sampled)
fast-json-stringify long string x 17,591 ops/sec ±0.20% (97 runs sampled)
fast-json-stringify-uglified long string x 17,170 ops/sec ±0.99% (93 runs sampled)
JSON.stringify short string x 5,741,197 ops/sec ±0.21% (96 runs sampled)
fast-json-stringify short string x 33,161,864 ops/sec ±0.53% (93 runs sampled)
fast-json-stringify-uglified short string x 32,049,135 ops/sec ±0.48% (94 runs sampled)
JSON.stringify obj x 2,145,600 ops/sec ±0.58% (93 runs sampled)
fast-json-stringify obj x 7,341,208 ops/sec ±0.61% (93 runs sampled)
fast-json-stringify-uglified obj x 7,281,431 ops/sec ±0.83% (91 runs sampled)

Looks OK to me.

If your schema doesn't contain any type arrays, the generated code is the same as before. However, the code generation itself could be a little slower.

// console.log(e)
// t.fail()
// }
// })
Copy link
Member

Choose a reason for hiding this comment

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

Do you think it would be feasible to also implement this feature? If not, we should at least throw a nice error that this is not supported and test that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll work on it tomorrow.

index.js Outdated
@@ -517,6 +551,7 @@ function buildArray (schema, code, name, externalSchema, fullSchema) {
condition += `Array.isArray(obj${accessor})`
break
default:
// TODO: item.type can be an array of types.
Copy link
Member

@mcollina mcollina Feb 22, 2018

Choose a reason for hiding this comment

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

is this todo related to the commented test?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. At this point we need to check if item.type is an array and then call into the switch statement from line 531 again for each element in the array. The switch statement should be factored out into a separate function.

@mcollina
Copy link
Member

Good work!

@florianreinhart
Copy link
Contributor Author

@mcollina I've now also added support for multiple types in tuples.

Copy link
Member

@delvedor delvedor left a comment

Choose a reason for hiding this comment

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

LGTM

var conditions = type.map((subType) => {
return buildArrayTypeCondition(subType, accessor)
})
condition = `(${conditions.join(' || ')})`
Copy link
Contributor Author

@florianreinhart florianreinhart Feb 23, 2018

Choose a reason for hiding this comment

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

There is potential for an optimization here. In the current implementation the generated code checks if the item matches any of the types. The nested() function basically performs the same check again using ajv. We could split this condition here into separate ones and use the knowledge of the item's type for the nested() function. However, this requires some more refactoring.

Copy link
Member

Choose a reason for hiding this comment

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

Feel free to experiment! We do like optimizations! :D

Copy link
Member

Choose a reason for hiding this comment

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

I'm landing this now, feel free to send a followup PR with the optimizations!

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

This should be good to go if benchmarks are still ok.

@florianreinhart
Copy link
Contributor Author

Same machine and node v8.9.4 as yesterday. Looks OK.

JSON.stringify array x 4,568 ops/sec ±0.72% (96 runs sampled)
fast-json-stringify array x 8,553 ops/sec ±1.13% (91 runs sampled)
fast-json-stringify-uglified array x 8,594 ops/sec ±0.62% (92 runs sampled)
JSON.stringify long string x 17,850 ops/sec ±0.50% (94 runs sampled)
fast-json-stringify long string x 17,881 ops/sec ±0.17% (97 runs sampled)
fast-json-stringify-uglified long string x 17,849 ops/sec ±0.56% (97 runs sampled)
JSON.stringify short string x 5,813,338 ops/sec ±0.23% (94 runs sampled)
fast-json-stringify short string x 33,805,913 ops/sec ±0.45% (95 runs sampled)
fast-json-stringify-uglified short string x 33,736,264 ops/sec ±0.31% (96 runs sampled)
JSON.stringify obj x 2,180,008 ops/sec ±0.19% (97 runs sampled)
fast-json-stringify obj x 7,575,110 ops/sec ±0.79% (94 runs sampled)
fast-json-stringify-uglified obj x 6,840,425 ops/sec ±1.36% (89 runs sampled)

@mcollina mcollina merged commit 668bd21 into fastify:master Feb 23, 2018
@florianreinhart florianreinhart deleted the array-of-types branch February 27, 2018 19:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants