ropensci / jsonvalidate

:heavy_check_mark::interrobang: Validate JSON
https://docs.ropensci.org/jsonvalidate
Other
49 stars 14 forks source link

Safe serialise #55

Closed richfitz closed 2 years ago

richfitz commented 3 years ago

This PR adds support for a schema-guided serialisation of R objects.

This is best described in the docs and example. Suppose we have this schema:

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "title": "Product",
    "description": "A product from Acme's catalog",
    "type": "object",
    "properties": {
        "id": {
            "description": "The unique identifier for a product",
            "type": "integer"
        },
        "name": {
            "description": "Name of the product",
            "type": "string"
        },
        "price": {
            "type": "number",
            "minimum": 0,
            "exclusiveMinimum": true
        },
        "tags": {
            "type": "array",
            "items": {
                "type": "string"
            },
            "minItems": 1,
            "uniqueItems": true
        }
    },
    "required": ["id", "name", "price"]
}

and we want to serialise this object:

x <- list(id = 1, name = "apple", price = 0.50, tags = "fruit")

If we use jsonlite::toJSON then id, name and price end up as length-1 arrays

{"id":[1],"name":["apple"],"price":[0.5],"tags":["fruit"]}

Alternatively if we pass auto_unbox = TRUE then tags gets turned into a string

{"id":1,"name":"apple","price":0.5,"tags":"fruit"}

so we typically end up manually marking strings to unbox with jsonlite::unbox. We can guide this though with the schema because we can work out what needs to be unboxed:

 jsonvalidate::json_serialise(x, schema)

giving

{"id":1,"name":"apple","price":0.5,"tags":["fruit"]}
richfitz commented 2 years ago

I've taken quite a different approach here in the end as I started writing out a json_serialiser object and realised that what we really needed was a reusable "things you can do with a schema" object. I doubt we'll find a 3rd thing but if we did we'd be sorted :)