Package: jsonbp
jsonbpjsonbp(JSON BluePrint) is a library to validate and deserialize JSON into
Python data based on a schema. There isjson-schemaand its
implementations already if you want a more mature and more widely used technique,
but I needed some features that were not easily available by just patching
json-schema, so this library is the result.jsonbp's design main goals were:schema reuse through import / type systemsupport for enumsbuilt in numeric fixed precision type (which deserializes directly into Python's Decimal)built in datetime type (which deserializes directly into Python's datetime)error reporting with support for localizationeasy to integrate and useContentsSchema definitionUsageRequirements and DependenciesInstallationDocumentationSchema definitionjsonbp uses its own (very simple) domain language to define a schema.
The only mandatory declaration is the"root"entry, which determines the expected
JSON contents. Here's a simple hypothetical example:root {
  x: float (min=0.0),
  y: float (min=0.0, max=1.0),
  
  optional color: {
    RED,
    GOLD,
    GREEN
  }
} [minLength=2]This defines a schema that represents an array of minimum length 2 whose
elements contain the fields 'x' and 'y' (where both 'x' and 'y' are not
allowed to be negative and 'y' is not allowed to be greater than 1.0) and
an optional field 'color' that can be either "RED", "GOLD" or "GREEN".
A JSON instance that obeys this schema is:[{"x":2.0,"y",0.004,"color":"RED"},{"x":3.0,"y",0.009},{"x":4.0,"y",0.016,"color":"GREEN"}]Besides"root", in jsonbp the following optional directives can be used to organize a schema:"type"-> to define specialized (restricted) simple types"node"-> to specify the contents of compound types (Objetcs)"enum"-> to define a list of allowed values for given fields"import"-> to reuse directives from existing blueprintsOne can then make use of these features to simplify and make the schema more
modular. In the above example schema, we could split the definitions and get
something more reusable, like the following:type non_negative : float (min=0.0)
type normalized : non_negative (max=1.0)

node coordinates {
  x: non_negative,
  y: normalized
}

include "color.jbp"
node colored_coordinates extends coordinates {
  optional color: color
}

root colored_coordinates[minLength=2]where the contents of file "color.jbp" would then be:enum color {
  RED,
  GOLD,
  GREEN
}(For detailed information using these directives, see theDocumentation section)UsageAll of jsonbp can be summarized in 2 functionalities:Schema parsingjsonbp.load(<schema file path>) => <blueprint object>jsonbp.loads(<schema string>) => <blueprint object>These functions are used for schema/blueprint loading.
Both do the same thing, the only difference is that the former expects a path to a file
storing the schema content while the latter expects a string with the schema content itself.
When there's a problem with the supplied schema, an exception is thrown. More on this can
be read onError handling and error localization. These functions, when
succeed loading the schema, return a blueprint instance that can then be used to deserialize
JSON strings.When loading a file, the blueprint is stored in a cache and associated with the absolute
path of that file. Thus, loading the same file twice won't make jsonbp parse it a second
time. To force the parsing of posterior calls toload(), calljsonbp.invalidateCache().JSON deserialization<blueprint object>.deserialize(<JSON string>) => (success, outcome)This is the only method that is intended to be invoked from the blueprint object returned
byload()/loads(). It expects a string holding the JSON contents to be deserialized. It
returns a tuple in the form(success, outcome).successbeing a boolean signalizing if
the deserialization was successful or not. If successful,outcomewill hold the Python data
obtained from the JSON string. Otherwise (successis false)outcomewill have a
message explaining what was not compliant according to the schema.ExampleHere's how one uses these functions in code:importjsonbpblueprint=jsonbp.loads('''root {success: {YES,NO}}''')jsonInstance='{ "success": "YES" }'success,outcome=blueprint.deserialize(jsonInstance)print(f'Success:{success}')print(f'Outcome:{outcome}')Requirements and Dependenciesjsonbp requires Python 3.6+, that's it.Under the hood, jsonbp usesPLYfor its schema parsing. PLY comes
included with jsonbp already, there's no need to download it separately.Installationjsonbp is available at PyPI:https://pypi.org/project/jsonbp/To install through pip:pipinstalljsonbpDocumentationThat was just an introduction, if you are interested in using jsonbp here are some more detailed information:Schema definitionError handling and error localizationSample of using jsonbp in Flask