Path or Expectation of FJS #532
Replies: 8 comments 51 replies
-
I want to discuss with you how FJS should work. Especially in terms of validation and output guarantees. Now FJS is a serializer with a mixin of validation checks. Some of these checks are required to define what to do with data (oneOf, anyOf, if/else). Some of these checks are not needed for serialization and check basic validation rules. There are two different points of how FJS should work.
const schema = {/*json schema*/}
const data = {/*input data*/}
// If you pass correct data it will work correctly
if (validate(data, schema)) {
const serializedData = FJS(data, schema)
const parsedData = JSON.parse(serializedData)
assert(validate(parsedData, schema)) // should always be true
}
// If you don't know that you input is valid, there is no guarantee that FJS produce valid output
const serializedData = FJS(data, schema) // might throw if can't produce the result, but doesn't have explicit validation checks
const parsedData = JSON.parse(serializedData)
assert(validate(parsedData, schema)) // unkown
const schema = {/*json schema*/}
const data = {/*input data*/}
const serializedData = FJS(data, schema) // if can't produce the correct (that will valid to the schema) output it will throw an error
const parsedData = JSON.parse(serializedData)
assert(validate(parsedData, schema)) // true If you have any other ideas, you can share them. |
Beta Was this translation helpful? Give feedback.
-
@Uzlopak Don't mind if I reply about the #520 case here.
|
Beta Was this translation helpful? Give feedback.
-
I'm not sure which option I should vote. Based on the json schema properties list there are edge cases, and filling out this matrix will explain how FJS should/will work
|
Beta Was this translation helpful? Give feedback.
-
Yes, this module is a standalone module usable by anyone to serialize data into a JSON representation. However, it is primarily developed to support Fastify. Fastify uses it to serialize response payloads by default and it is advertised to do so. The module should continue to provide the expectations that Fastify has around response serialization. That includes throwing an error when the data is missing required properties for the response to be valid. |
Beta Was this translation helpful? Give feedback.
-
fast-json-stringify was designed to be a serializer. However, I added some basic validation, like Performing full validation would slow it to a halt, make it useless. Some validation is also needed to support all the JSON Schema features. |
Beta Was this translation helpful? Give feedback.
-
I made the PRs #611 and #579 to get some ground to talk. But to be frank, i am quite dissapointed as there is no clear goal to reach. |
Beta Was this translation helpful? Give feedback.
-
It might be good to design a pluggable compiler. So anyone could write his own plugin and inject some code into the precompiled serialization function. After that, we could insert into the code any validation or type coercion without modifying the compiler core module. const compiler = new Compiler({
preArraySerializationHook: (ctx, array, arraySchema) => {
if (array.length !== arraySchema.lenght) {
throw new Error ('Array has wrong length')
}
},
preIntegerSerializationHook: () => {},
preObjectSerializationHook: () => {},
// ...
preSchemaSerializationHooks: {
'schema-1': () => {},
'schema-2': () => {},
}
})
const serialize = compiler.build(schema, {
// pre serialization hooks only for this schema
})
serialize(object) P.S. I'm not sure that it's possible to write it, but I would try. |
Beta Was this translation helpful? Give feedback.
-
Currently: If we have a schema: If we have a schema: If we have a schema: If we have a schema: ( This existing behaviour seems inconsistent and surprising. I don't think fast-json-stringify should ever do a type coercion that That is, I think that the design goal of FJS should be a new option 3:
Properties missing from the value that are in the schema should always be omitted (even if the schema defines a default or const), and the result will always match the parts of the schema for which data is returned. I don't think FJS should ever throw on a value that does not match the schema (including in the cases where it currently does throw, like providing an object for a number). If you want full validation, just validate your value with AJV before stringifying it. But this raises a problem with anyOf/allOf/if-else: in these cases. For example, if we have: schema:
What should Serialising these constructs is always going to be slower, because we need to check which option to proceed with before doing the serialisation. So the easy option would just be to give up and call I think it would be reasonable to instead restrict the ways that anyOf, oneOf, allOf, if-else can be used in schemas that are to be used with fast-json-stringify:
These properties of the schema should be checked at compile time, and ignored or throw, depending on a strict option. If they are ignored, the corresponding parts of a schema would be omitted from serialisation (not just delegated to JSON.stringify). So for example a property with a oneOf subschema without a discriminator keyword would always be omitted from serialisation, regardless of the value passed, or would throw at compile time if compiled with a strict option. I think this approach would provide an easy to understand, consistent, fast, and safe* way of serialising data, and clearly defines what fast-json-stringify does (serialisation), and does not do (validation of the data to be serialised). *The safety that I think matters most in the context of serialising data for an API is making sure that only data that the programmer intends to be serialised is serialised (preventing unexpected data leaking in an API). I appreciate that this approach would be a big change from the current behaviour, but having poked around fast-json-schema a bit recently, I thought this view of things might be useful, and this thread seemed like the place for this discussion. |
Beta Was this translation helpful? Give feedback.
-
Within the discussion inside #530.
I believe we are lost on the path or expectation of this module.
It is clear that we divide into two separate opinion.
FJS should be a plain serializer, we shouldn't care on the validation.
FJS should be a serializer that return the
value
can be validate against theJSON-Schema
.I open a poll here to helps us make decision on which path should we go.
3 votes ·
Beta Was this translation helpful? Give feedback.
All reactions