Skip to content

Latest commit

 

History

History
49 lines (30 loc) · 4.53 KB

EXTENSIONS.md

File metadata and controls

49 lines (30 loc) · 4.53 KB

Extensions

presilo tries to comply to the json-schema as closely as possible. Effort is put into making it strictly read what the spec writes. However, there are cases where practical utility is hampered by this, since presilo is doing a great deal more work with schemas than most other applications do. This document lists out the deviations and extensions to the official json-schema spec.

minByteLength and maxByteLength

Because the author often finds himself working at a binary level, or with types that strictly require certain string byte lengths, two extension properties are added to string schemas.

  • minByteLength: Represents a constraint on the minimum allowable byte length of a string. It is used similarly to minLength.
  • maxByteLength: Represents a constraint on the maximum allowable byte length of a string. It is used similarly to maxLength.

Note that this byte length interpretation is only valid in non-dynamic languages - there is currently no support for python, ruby, or mysql. The author plans to implement support for those when he has more time.

Limitations

presilo tries to port all concepts between all implemented languages. Code generated by presilo is intended to work contractually the same between all languages. Unfortunately, this places certain limitations on the amount of features actually allowable in schemas used by presilo.

Multiple types

presilo does not support an array in the place of the type field of any schema, unless it contains exactly two members, and one of those members is null. presilo interprets this to mean "nullable", and will allow null values to be set on that field in generated code. The "type" of the field is the other member of the array, and must be a valid type.

mysql

While presilo does what it can to make meaningful schema constraints for mysql queries, it's not always possible. This section lists out where mysql queries are semantically changed from what one might expect:

  • Generates one query file to represent all data structures
  • Uses "module" not as a harmless namespace, but as the DB name tables should be contained
  • Does not attempt to represent arrays
  • Assumes internationalized "nvarchar" for all strings
  • Provides a best guess for string column length based on constraints for min/max length
  • Does not provide a primary key!
  • Does not support regex constraints.
  • Uses 'bit' to represent booleans, with 0 = true, 1 = false.
  • Does not support minimum byte length constraints

Mixin $ref schemas

Normally when a $ref is made to another schema, it's possible to add extra constraints on top of that ref. For instance, you might reference a number field that normally has no maximum size, but you want to impose a maximum size on a specific use of that schema. This is not supported - make a new schema or definition. Any field that exists sibling to $ref is ignored completely.

The thought behind the specification's use of $ref being so permissive is for validators. This tool is not a validator. Semantically, changing anything about a $ref is a copy-on-write, and so creates a new schema. This is possible in presilo, but due to technical preference, it's unallowed. All references must be leafs in the tree that represents the parsing. This makes parsing much more reliable and easy, and makes the most sense given the nature of the codegen.

golang marshalling/unmarshalling

Golang has the concept of 'exported' and 'unexported' fields. This matters a great deal when marshalling/unmarshalling, since only exported fields are marshalled. Normally, if a field has constraints, one might expect that the field would be unexported, with getter/setter routines. However, presilo generates only exported fields, so anything put into a schema file will be accessible publicly.

This is an intentional decision based on experience trying to extend marshalling/unmarshalling support to multiple encodings. In some (json), it's easy enough to simply implement an interface that uses only primitive types, and a certain amount of under-the-covers indirection can be used to make sure that marshalling a codegen'd struct will actually export all fields.

However, in most encodings (bson, xml, etc) there is a certain amount of library-specific knowledge required in order to marshal/unmarshal. presilo is not particularly interested in maintaining every encoding/decoding interface's specification, nor with requiring the user to pull down third-party libraries (such as bson) just to build objects. So the decision was made to export all fields.