How to convert JSON schema into the OCaml/ReasonML type

Viewed 335

There is a JSON file, it has been converted to JSON-schema and the schema definition in ReasonML type. Please help to comment the following issues.

  1. Is it a good choose to use JSON schema as a table/schema definition? It seems it is a de-facto standard to define tables/schemas. If it is not the suggested method, please suggest me a method to resolve this issue.
  2. Is it possible to define type dynamically? I would save all tables/schemas definition and data into a single JSON file. When I decode the JSON file, all definition and data should be defined as type in OCaml/ReasonML simultaneously. There is an alternative that I can convert all tables/schemas into type by coding but I would make these as flexible as possible.

Thank you.

List 1 :Stocks.json

[
    {
        "code": "AAPL.US",
        "timestamp": 1584388800,
        "gmtoffset": 0,
        "open": 241.95,
        "high": 259.08,
        "low": 240,
        "close": 242.21,
        "volume": 80605865,
        "previousClose": 277.97,
        "change": -35.76,
        "change_p": -12.865
    },
    {
        "code": "ABPL.US",
        "timestamp": 1584388800,
        "gmtoffset": 0,
        "open": 241.95,
        "high": 259.08,
        "low": 240,
        "close": 242.21,
        "volume": 80605865,
        "previousClose": 277.97,
        "change": -35.76,
        "change_p": -12.865
    }
]

List 2: According to the standard of json-schema.org, JSON Schema was generated from List 1.

{
    "$schema": "http://json-schema.org/draft-07/schema",
    "$id": "http://example.com/example.json",
    "type": "array",
    "readOnly": false,
    "writeOnly": false,
    "uniqueItems": false,
    "minItems": 0,
    "minContains": 1,
    "title": "The Root Schema",
    "description": "The root schema comprises the entire JSON document.",
    "additionalItems": true,
    "items": {
        "$id": "#/items",
        "type": "object",
        "readOnly": false,
        "writeOnly": false,
        "minProperties": 0,
        "title": "The Items Schema",
        "description": "An explanation about the purpose of this instance.",
        "default": {},
        "examples": [
            {
                "code": "AAPL.US",
                "previousClose": 277.97,
                "timestamp": 1584388800.0,
                "change": -35.76,
                "close": 242.21,
                "open": 241.95,
                "gmtoffset": 0.0,
                "volume": 80605865.0,
                "low": 240.0,
                "high": 259.08,
                "change_p": -12.865
            },
            {
                "volume": 80605865.0,
                "low": 240.0,
                "high": 259.08,
                "change_p": -12.865,
                "previousClose": 277.97,
                "code": "ABPL.US",
                "timestamp": 1584388800.0,
                "open": 241.95,
                "close": 242.21,
                "change": -35.76,
                "gmtoffset": 0.0
            }
        ],
        "additionalProperties": true,
        "required": [
            "code",
            "timestamp",
            "gmtoffset",
            "open",
            "high",
            "low",
            "close",
            "volume",
            "previousClose",
            "change",
            "change_p"
        ],
        "properties": {
            "code": {
                "$id": "#/items/properties/code",
                "type": "string",
                "readOnly": false,
                "writeOnly": false,
                "minLength": 0,
                "title": "The Code Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": "",
                "examples": [
                    "AAPL.US"
                ]
            },
            "timestamp": {
                "$id": "#/items/properties/timestamp",
                "type": "integer",
                "readOnly": false,
                "writeOnly": false,
                "title": "The Timestamp Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": 0,
                "examples": [
                    1584388800
                ]
            },
            "gmtoffset": {
                "$id": "#/items/properties/gmtoffset",
                "type": "integer",
                "readOnly": false,
                "writeOnly": false,
                "title": "The Gmtoffset Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": 0,
                "examples": [
                    0
                ]
            },
            "open": {
                "$id": "#/items/properties/open",
                "type": "number",
                "readOnly": false,
                "writeOnly": false,
                "title": "The Open Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": 0,
                "examples": [
                    241.95
                ]
            },
            "high": {
                "$id": "#/items/properties/high",
                "type": "number",
                "readOnly": false,
                "writeOnly": false,
                "title": "The High Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": 0,
                "examples": [
                    259.08
                ]
            },
            "low": {
                "$id": "#/items/properties/low",
                "type": "integer",
                "readOnly": false,
                "writeOnly": false,
                "title": "The Low Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": 0,
                "examples": [
                    240
                ]
            },
            "close": {
                "$id": "#/items/properties/close",
                "type": "number",
                "readOnly": false,
                "writeOnly": false,
                "title": "The Close Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": 0,
                "examples": [
                    242.21
                ]
            },
            "volume": {
                "$id": "#/items/properties/volume",
                "type": "integer",
                "readOnly": false,
                "writeOnly": false,
                "title": "The Volume Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": 0,
                "examples": [
                    80605865
                ]
            },
            "previousClose": {
                "$id": "#/items/properties/previousClose",
                "type": "number",
                "readOnly": false,
                "writeOnly": false,
                "title": "The Previousclose Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": 0,
                "examples": [
                    277.97
                ]
            },
            "change": {
                "$id": "#/items/properties/change",
                "type": "number",
                "readOnly": false,
                "writeOnly": false,
                "title": "The Change Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": 0,
                "examples": [
                    -35.76
                ]
            },
            "change_p": {
                "$id": "#/items/properties/change_p",
                "type": "number",
                "readOnly": false,
                "writeOnly": false,
                "title": "The Change_p Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": 0,
                "examples": [
                    -12.865
                ]
            }
        }
    }
}

List 3: Corresponding ReasonML Type.

 type position = {
    symbol: string,
    holding: int,
    pprice: float,
  };

  type account = {
    name: string,
    max_ind_holding: float,
    pos: list(position),
  };
1 Answers

I also tried a similar thing and didn't find a tl;dr-Solution. So, i cannot provide you one.

Anyways, i can recommend 2 half-solutions, maybe adding up to a whole one:

1. graphql-codegen As you mentioned GraphQL, using schema-ast-plugin together with reason-plugin you can go from your JSON-schema to ReasonML Types. (see Note at the end)

2. quicktype which can generate types for a lot of languages. Unfortunately, ReasonML is still missing. But you can find progress and instructions on how to add a new language here: Language request: OCaml / Reason

3. Combine 1&2 for JSON as your starting point

You could try to go from JSON to typescript(or any other language supported by graphql-codegen) and than typescript (or language x) to GraphQL using graphql-codegen-typescript and finally from typescript to ReasonML :)

I know, none of this is convenient and involves reading/testing a lot, but i hope you find it helpful and at least come closer to your goal.

Note: If you are compiling to JS using bucklescript 7: graphql-codegen-reason was not updated a while. So it doesn't take advantage of bucklescript 7's new feature to compile records directly into JS-Objects. Instead it uses Js.t, which i find unnecessary and annoying, as you could have more clean types. I tried to change it, but I'm still too inexperienced in ReasonML, so it does only work for specific cases and is full of bugs. Therefore, not published anywhere. If your interested nevertheless, i can push it (no guarantees as you can guess :) ). Just let me know.

Related