如何为闪卡应用构建用于导入导出的合法JSON-LD结构
下面针对你提出的5个疑问逐一解答:
1. FlashCardSide与Dictionary的语言关联是否建立?
已经建立了有效关联。你的FlashCardSide通过isPartOf属性引用了Language的IRI(比如ex:language/norwegian),而Dictionary的availableLanguage数组里的Language对象正好使用了相同的IRI作为id。在JSON-LD中,相同的IRI就代表同一个实体,这种引用方式就是标准的关联手段。
2. FlashCard用schema:Thing但包含非标准属性为何通过验证?
schema:Thing是schema.org体系中最顶层的通用类型,本身就允许扩展自定义属性。验证工具主要检查JSON-LD的语法正确性、基本的schema类型兼容性,不会强制要求所有属性都必须是schema.org的标准属性。只要你的JSON-LD结构合法,自定义属性就能通过验证。
如果想让结构更规范,你可以考虑把contains定义为显式的自定义属性(参考问题3的方法),或者替换成schema.org中更贴合的属性(比如schema:hasPart),不过当前写法完全合法。
3. 如何定义schema.org以外的自定义类型和属性?
通过JSON-LD的@context就能轻松定义:
- 自定义类型:先定义一个命名空间前缀(比如你的
"ex": "https://example.com/"),然后把类型名称映射到该前缀下的IRI,比如"Dictionary": "ex:Dictionary",这样Dictionary就对应https://example.com/Dictionary这个自定义类型。 - 自定义属性:同样在
@context中添加映射,比如你当前的contains没有显式定义,建议补充"contains": "ex:contains",这样contains属性的IRI就是https://example.com/contains,明确是你的自定义属性,避免歧义。
修改后的@context片段示例:
"@context": { "ex": "https://example.com/", "schema": "http://schema.org/", "id": "@id", "type": "@type", "Dictionary": "ex:Dictionary", "FlashCardSide": "ex:FlashCardSide", "contains": "ex:contains", // 其他已有映射... }
4. 是否需要部署ontology.jsonld定义文件?
不是必须的。如果只是你自己的应用内部做导入导出,只要应用能正确解析这些自定义类型和属性,完全不需要部署任何外部定义文件。
但如果你的数据需要对外共享(比如给其他开发者工具使用),部署一个机器可读的本体文件能让第三方更好地理解你自定义术语的含义、属性的预期类型等,这时候就值得部署。
5. 如何定义acceptedValue属性?
acceptedValue是你自定义的属性,按照问题3的方法,在@context中添加映射即可:
"@context": { // 已有映射... "acceptedValue": "ex:acceptedValue" }
这样acceptedValue就对应https://example.com/acceptedValue这个自定义属性。如果需要进一步定义该属性的细节(比如预期值是字符串数组),可以在本体文件中补充描述,但如果只是应用内部使用,只需要在@context中完成映射,然后在数据里按数组格式使用就足够了。
优化后的JSON-LD示例代码
{ "@context": { "ex": "https://example.com/", "schema": "http://schema.org/", "id": "@id", "type": "@type", "Dictionary": "ex:Dictionary", "Language": "schema:Language", "FlashCard": "schema:Thing", "FlashCardSide": "ex:FlashCardSide", "availableLanguage": "schema:availableLanguage", "name": "schema:name", "value": "schema:value", "description": "schema:description", "isPartOf": "schema:isPartOf", "itemListElement": "schema:itemListElement", "contains": "ex:contains", "acceptedValue": "ex:acceptedValue" }, "id": "ex:dictionary/0117649e-f5af-486e-9d4d-756c335f7e53", "type": "Dictionary", "availableLanguage": [ { "id": "ex:language/norwegian", "type": "Language", "name": "norsk" }, { "id": "ex:language/english", "type": "Language", "name": "english" } ], "itemListElement": [ { "id": "ex:flashcard/0117649e-f5af-486e-9d4d-756c335f7e51", "type": "FlashCard", "contains": [ { "type": "FlashCardSide", "value": "hund", "isPartOf": "ex:language/norwegian", "acceptedValue": ["random-123"], "description": "<p>additional details</p>" }, { "type": "FlashCardSide", "value": "dog", "isPartOf": "ex:language/english", "acceptedValue": ["random-123"], "description": "<p>additional details</p>" } ] }, { "id": "ex:flashcard/0117649e-f5af-486e-9d4d-756c335f7e52", "type": "FlashCard", "contains": [ { "type": "FlashCardSide", "value": "eple", "isPartOf": "ex:language/norwegian", "acceptedValue": ["random-321"], "description": "<p>additional details</p>" }, { "type": "FlashCardSide", "value": "apple", "isPartOf": "ex:language/english", "acceptedValue": ["random-321"], "description": "<p>additional details</p>" } ] } ] }
内容的提问来源于stack exchange,提问作者Constantin.FF

