最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - json-schema: how to transform from one json-schema to another - Stack Overflow

programmeradmin5浏览0评论

I have the two different json-schemas:

schemaA -> A calendar as defined at

{
    "$schema": "",
    "description": "A representation of an event",
    "type": "object",
    "required": [ "dtstart", "summary" ],
    "properties": {
        "dtstart": {
            "format": "date-time",
            "type": "string",
            "description": "Event starting time"
        },
        "dtend": {
            "format": "date-time",
            "type": "string",
            "description": "Event ending time"
        },
        "summary": { "type": "string" },
        "location": { "type": "string" },
        "url": { "type": "string", "format": "uri" },
        "duration": {
            "format": "time",
            "type": "string",
            "description": "Event duration"
        },
        "rdate": {
            "format": "date-time",
            "type": "string",
            "description": "Recurrence date"
        },
        "rrule": {
            "type": "string",
            "description": "Recurrence rule"
        },
        "category": { "type": "string" },
        "description": { "type": "string" },
        "geo": { "$ref": "http: //json-schema/geo" }
    }
}

schemaB -> Another calendar schema (also json-schema version draft-04)

My quesiton is simple. I have a javascript object 'calendarA' that follows the first schema, i.e.,

validates(calendarA, schemaA); // true

I want to describe a transformation between the schemas, i.e., from schemaA to schemaB, so I can pass calendarA as input and get a new calendarB that fits schemaB. Put it in code:

var calendarB = fromSchemaAtoB(calendarA, schemaA, schemaB);
validates(calendarB, schemaB); // true

From your point of view which is the best approach/tools to write fromSchemaAtoB guys? I really want to describe transfomations using the schemas, something like:

schemaB.properties.foo = schemaA.properties.dtstart

I saw a lot of basic json transformation packages but it seems to me that in most of them you specify your output as external templates that do not take into account the schemas (so result could be invalid with respect to schemaB).

Thank you so much in advance!!

JG

PS: I prefer javascript based solutions if possible but I am really open to any possibility.

EDIT 1: To clarify after reading @jason's answer, the question is how to better describe such relations between schemas and how to apply them to obtain calendarB. So if you prefer:

var calendarB = transform(calendarA, schemaA, schemaB, relationsAtoB);
validates(calendarB, schemaB); // true

and the question then is how to better describe "relationsAtoB" and how to implement the "transform" function.

I have the two different json-schemas:

schemaA -> A calendar as defined at http://json-schema/calendar

{
    "$schema": "http://json-schema/draft-04/schema#",
    "description": "A representation of an event",
    "type": "object",
    "required": [ "dtstart", "summary" ],
    "properties": {
        "dtstart": {
            "format": "date-time",
            "type": "string",
            "description": "Event starting time"
        },
        "dtend": {
            "format": "date-time",
            "type": "string",
            "description": "Event ending time"
        },
        "summary": { "type": "string" },
        "location": { "type": "string" },
        "url": { "type": "string", "format": "uri" },
        "duration": {
            "format": "time",
            "type": "string",
            "description": "Event duration"
        },
        "rdate": {
            "format": "date-time",
            "type": "string",
            "description": "Recurrence date"
        },
        "rrule": {
            "type": "string",
            "description": "Recurrence rule"
        },
        "category": { "type": "string" },
        "description": { "type": "string" },
        "geo": { "$ref": "http: //json-schema/geo" }
    }
}

schemaB -> Another calendar schema (also json-schema version draft-04)

My quesiton is simple. I have a javascript object 'calendarA' that follows the first schema, i.e.,

validates(calendarA, schemaA); // true

I want to describe a transformation between the schemas, i.e., from schemaA to schemaB, so I can pass calendarA as input and get a new calendarB that fits schemaB. Put it in code:

var calendarB = fromSchemaAtoB(calendarA, schemaA, schemaB);
validates(calendarB, schemaB); // true

From your point of view which is the best approach/tools to write fromSchemaAtoB guys? I really want to describe transfomations using the schemas, something like:

schemaB.properties.foo = schemaA.properties.dtstart

I saw a lot of basic json transformation packages but it seems to me that in most of them you specify your output as external templates that do not take into account the schemas (so result could be invalid with respect to schemaB).

Thank you so much in advance!!

JG

PS: I prefer javascript based solutions if possible but I am really open to any possibility.

EDIT 1: To clarify after reading @jason's answer, the question is how to better describe such relations between schemas and how to apply them to obtain calendarB. So if you prefer:

var calendarB = transform(calendarA, schemaA, schemaB, relationsAtoB);
validates(calendarB, schemaB); // true

and the question then is how to better describe "relationsAtoB" and how to implement the "transform" function.

Share Improve this question edited Jul 25, 2016 at 7:07 user6614015 asked Jul 20, 2016 at 14:10 user6614015user6614015 1111 gold badge1 silver badge5 bronze badges 9
  • Hi, please tell me what do you prefer, transforming scheme data before creating object or mutating existing object to another one? – Appeiron Commented Jul 20, 2016 at 14:36
  • var calendarB = fromSchemaAtoB(calendarA, schemaA, schemaB); if you really sure you want to transform shemeA to schemeB instead of mutating ObjectA, you need instead of schemeB a template that will describe relations of properties in schemeA to dedicated properties in schemeB. If you do not like creating templates, fromSchemaAtoB() should do every transformation without template (but this is very unsupportable approach, better to have CONFIG to be changed instead of method itself) – Appeiron Commented Jul 20, 2016 at 14:45
  • Hi. If by "transforming scheme data before creating object" you mean the second object is a pletely new one, I would say I prefer this option. Your second option is very interesting also specially for large objects that I want to mutate for performance reasons. I guess that the ideal framework should purpose both transformation types, a default one that creates a entire new object, and a second one that mutates the input object. But for now new objects. Thanks @Appeiron – user6614015 Commented Jul 20, 2016 at 14:45
  • Previous answer was for your first ment. For the second ment, just to clarify, schemas should not mutate. They should be the same before and after a transformation. – user6614015 Commented Jul 20, 2016 at 15:27
  • For easy transformation, it's good to have Template that you will decorate with ining data and relying on configuration you passed about relations you have between two schemes: jsfiddle/unLjLtey/2 It's depending on you what to do with other properties, not defined in relations, should transformer copy them or leave without touching. – Appeiron Commented Jul 20, 2016 at 16:24
 |  Show 4 more ments

2 Answers 2

Reset to default 7

I believe a library like this could be used to address your question. This does not directly address the question (transforming from one JSON schema to the other) but what you can do (which is what I am currently doing) is the following:

  1. Specify a JSON schema for your input
  2. Specify a JSON schema for your output
  3. Specify a mapping template (e.g. using the library I referenced).

Of course, ideally you would not have to do both 2 and 3 but I have not found something which does this automatically. So, for example, you could specify the mapping template and create some library function which takes that as well as the JSON schema in 1 as its inputs, and would generate the JSON schema in 3 as its output.

This, however, is not trivial so currently I am specifying both 2 and 3.

Also, keep in mind that you cannot have 1 and 2 and somehow automatically generate 3. This is because there are more than one mapping functions that would take data adhering to schema 1 and produce data adhering to schema 2.

This is not something that JSON Schema is designed for. Transforming JSON from one JSON Schema to another requires a human to provide context for the transformation.

For example, here is a fairly simple transformation for a human to do.

jsonA

{
  "key1": "value1",
  "key2": "value2"
}

schemaA

{
  "type": "object",
  "additionalProperties": {
    "type": "string"
  }
}

schemaB

{
  "type": "array",
  "items": {
    "type": "array",
    "items": [
      { "type": "string" },
      { "type": "string" }
    ]
  }
}

Can you figure out what the transformation should be from this information alone? Maybe, but there are too many ambiguities for it to be done problematically. This transformation converts an object to an array of key/value pairs.

jsonB

[
  ["key1", "value1"],
  ["key2", "value2"]
]

Because of the ambiguity paring schemas, just about any transformations will have to be done manually on a case-by-case basis. I don't think you will get very far with this approach.

JSON-LD

You might want to look into JSON-LD as an alternative. A JSON-LD document describes data as a directed graph. Consequently, there are multiple ways a JSON-LD document can be expressed as a JSON object. In JSON-LD, this is called framing.

The idea would be to describe your calendar as a JSON-LD document that can be framed to match either schemaA or schemaB. To put it another way, the JSON-LD document is the context needed to remove the ambiguities between the schemas. I would show an example, but I don't know JSON-LD that well. I'll leave it to you it look into it if you think it might solve your problem.

发布评论

评论列表(0)

  1. 暂无评论