Json-Schema:如何从一个Json-Schema转换为另一个

10

我有两个不同的JSON模式:

schemaA -> 此日历定义在http://json-schema.org/calendar

{
    "$schema": "http://json-schema.org/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.org/geo" }
    }
}

schemaB -> 另一种日历模式(也是json-schema版本草案-04)

我的问题很简单。我有一个遵循第一个模式的javascript对象'calendarA',即

validates(calendarA, schemaA); // true

我想描述一个模式之间的转换,即从schemaA到schemaB,这样我就可以将calendarA作为输入传递,并得到适合schemaB的新calendarB。放在代码中:

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

从您的角度来看,编写从模式A到模式B的转换应该采用哪种方法/工具最佳?我真的希望能够使用这些模式来描述转换,例如:

schemaB.properties.foo = schemaA.properties.dtstart
我看到很多基本的JSON转换包,但在大多数情况下,它们都是将输出指定为外部模板,而不考虑模式(因此结果可能与schemaB不符合)。非常感谢您提前的帮助!
JG
注:如果可能的话,我更喜欢基于JavaScript的解决方案,但我真的很开放任何可能性。
编辑1:在阅读@jason的答案后澄清,问题是如何更好地描述模式之间的关系以及如何应用它们来获得calendarB。所以,如果您愿意:
var calendarB = transform(calendarA, schemaA, schemaB, relationsAtoB);
validates(calendarB, schemaB); // true

问题是如何更好地描述“关系A到B”,以及如何实现“transform”函数。


你好,请告诉我,你更喜欢在创建对象之前转换方案数据还是将现有对象变异为另一个对象? - Appeiron
如果您确信要将schemaA转换为schemaB而不是改变ObjectA,则需要使用模板来描述schemeA中属性与schemeB中专用属性之间的关系,而不是使用schemeB。如果您不喜欢创建模板,则fromSchemaAtoB()应该可以在没有模板的情况下完成每个转换(但这是非常不可维护的方法,最好更改CONFIG而不是方法本身)。 - Appeiron
嗨。如果您所说的“在创建对象之前转换方案数据”意味着第二个对象是全新的,我会说我更喜欢这个选项。您的第二个选项也非常有趣,特别是对于我想要为性能原因而突变的大型对象。我想理想的框架应该提供这两种转换类型,一个默认创建一个全新的对象,另一个则突变输入对象。但现在选择新对象。谢谢@Appeiron - user6614015
之前的回答是针对您的第一条评论。就第二条评论而言,需要澄清的是,模式不应该发生变化。在转换前后,它们应该保持不变。 - user6614015
谢谢@Appeiron,您能否提供一个模板方法的示例作为答案,以便我可以接受它是否可行?请参见我上面的更新。再次感谢。 - user6614015
显示剩余4条评论
2个回答

6
我认为像这个库这样的工具可用于解决您的问题。虽然它不能直接解决从一个JSON模式转换到另一个JSON模式的问题,但您可以使用以下方法(这也是我目前正在做的):

  1. 指定输入的JSON模式
  2. 指定输出的JSON模式
  3. 指定映射模板(例如使用我提到的库)。

当然,理想情况下,您不必同时进行第2和第3步,但我还没有找到自动执行此操作的工具。因此,例如,您可以指定映射模板,并创建一些库函数,该函数将其作为输入并将JSON模式1中的数据一起作为输入,并将JSON模式3生成为输出。

但是,这并不容易,所以我目前正在指定第2步和第3步。

另外,请记住,您不能同时拥有1和2,并自动生成3。这是因为有多个映射函数可以获取符合模式1的数据,并产生符合模式2的数据。


3
这不是JSON Schema的设计目的。将JSON从一个JSON Schema转换到另一个需要人为提供转换的上下文信息。
例如,以下是一个相当简单的需要人工完成的转换。 jsonA
{
  "key1": "value1",
  "key2": "value2"
}

模式A

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

模式B

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

仅凭这些信息,你能确定转换应该是什么吗?也许可以,但有太多的歧义,无法进行问题解决。此转换将对象转换为键/值对数组。

jsonB

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

由于比较模式的歧义性,任何转换都必须根据具体情况手动完成。我认为您采用这种方法不会有很大进展。
JSON-LD
您可能想要考虑 JSON-LD 作为替代方案。 JSON-LD 文档将数据描述为有向图。 因此,可以通过多种方式将 JSON-LD 文档表示为 JSON 对象。 在 JSON-LD 中,这称为 framing
思路是将您的日历描述为可以框架匹配 schemaA 或 schemaB 的 JSON-LD 文档。 换句话说,JSON-LD 文档是消除模式之间歧义的上下文所需的内容。 我可以展示一个例子,但我不太了解 JSON-LD。 如果您认为它可能解决您的问题,我会让您自己研究一下。

谢谢@jason,我刚刚添加了更多信息来澄清模式之间的关系必须提供的事实。JSON-LD看起来很有趣。您能否提供一个使用框架方法使用JSON-LD的示例?谢谢。 - user6614015
你好,你找到解决方案了吗?最终你采取了哪种方法? - Abhilash

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接