Как ссылаться на внешние файлы с помощью JSON.net?

Вот ошибка, которую я получаю, когда JSON.net пытается прочитать мою схему JSON ( return JsonSchema.Read(new JsonTextReader(reader)); ):

2014-07-15 15:33:42.7011 [Fatal] Newtonsoft.Json.JsonException: Could not resolve schema reference 'data-result.json'.
   at Newtonsoft.Json.Schema.JsonSchemaBuilder.ResolveReferences(JsonSchema schema) in c:\Development\Releases\Json\Work
ing\Newtonsoft.Json\Src\Newtonsoft.Json\Schema\JsonSchemaBuilder.cs:line 139
   at Newtonsoft.Json.Schema.JsonSchemaBuilder.ResolveReferences(JsonSchema schema) in c:\Development\Releases\Json\Work
ing\Newtonsoft.Json\Src\Newtonsoft.Json\Schema\JsonSchemaBuilder.cs:line 179
   at Newtonsoft.Json.Schema.JsonSchemaBuilder.Read(JsonReader reader) in c:\Development\Releases\Json\Working\Newtonsof
t.Json\Src\Newtonsoft.Json\Schema\JsonSchemaBuilder.cs:line 85
   at Newtonsoft.Json.Schema.JsonSchema.Read(JsonReader reader, JsonSchemaResolver resolver) in c:\Development\Releases\
Json\Working\Newtonsoft.Json\Src\Newtonsoft.Json\Schema\JsonSchema.cs:line 280
   at Newtonsoft.Json.Schema.JsonSchema.Read(JsonReader reader) in c:\Development\Releases\Json\Working\Newtonsoft.Json\
Src\Newtonsoft.Json\Schema\JsonSchema.cs:line 266
   at ThinkBinary.SchemaToPoco.Core.JsonSchemaToCodeUnit.LoadSchema(String file) in c:\Users\SLiu\Projects\json-schema-t
o-poco\Source\ThinkBinary.SchemaToPoco.Core\JsonSchemaToCodeUnit.cs:line 70
   at ThinkBinary.SchemaToPoco.Core.JsonSchemaToCodeUnit..ctor(String schemaDocument, String requestedNamespace) in c:\U
sers\SLiu\Projects\json-schema-to-poco\Source\ThinkBinary.SchemaToPoco.Core\JsonSchemaToCodeUnit.cs:line 19
   at ThinkBinary.SchemaToPoco.Console.Program.Main(String[] args) in c:\Users\SLiu\Projects\json-schema-to-poco\Source\
ThinkBinary.SchemaToPoco.Console\Program.cs:line 38

Моя схема JSON:

{
  "$schema": "http://json-schema.org/draft-03/schema#",
  "title": "DataSet",
  "description": "A result set and description of measures and values",
  "type": "object",
  "properties": {
    "results": {
      "$ref": "data-result.json"
    },
    "dimensions": {
      "type": "array",
      "description": "An array of data dimensions included in a result set",
      "items": {
        "$ref": "data-dimension.json"
      },
      "uniqueItems": true
    },
    "measure": {
      "$ref": "data-measure.json",
      "description": "single measure represented in this data set."
    }
  },
}

Моя проблема в том, что у меня есть эта схема JSON с этой ссылкой на внешний файл, data-result.json, но JSON.net еще не знает, что он существует. Есть ли какое-то решение для этого? У меня есть одна идея: просмотреть схему и, если есть какие-либо ссылки на внешние файлы, проанализировать те из них, у которых есть общий JsonSchemaResolver. Мне пришлось бы добавить соответствующие идентификаторы, поскольку похоже, что $ref любит сопоставляться по идентификатору, хотя на json-schema.org есть явные примеры использования $ref с имена файлов. Я хотел бы знать, есть ли лучший способ, чтобы JSON.net изначально поддерживал ссылки на внешние схемы.

Исходный код размещен на Github, если это поможет. Я протестировал с удаленным полем $ref, и он успешно компилируется.


person sbl03    schedule 15.07.2014    source источник


Ответы (3)


В схеме Json.NET значительно улучшена поддержка разрешения внешних ссылок.

Подробнее читайте здесь: http://www.newtonsoft.com/jsonschema/help/html/LoadingSchemas.htm

person James Newton-King    schedule 28.01.2015

У меня есть одна идея: просмотреть схему и, если есть какие-либо ссылки на внешние файлы, проанализировать те из них, которые имеют общий JsonSchemaResolver

Да, вам нужно знать, от каких схем зависит ваша схема, сначала проанализировать их и добавить в файл JsonSchemaResolver. Схемы будут разрешены с использованием их идентификаторов.

Вот пример (с использованием синтаксиса draft-03):

var baseSchema = JsonSchema.Parse(@"
{
  ""$schema"": ""http://json-schema.org/draft-03/schema#"",
  ""id"": ""http://mycompany/base-schema#"",
  ""type"": ""object"",

  ""properties"": {
    ""firstName"": { ""type"": ""string"", ""required"": true}
  }
}
");

var resolver = new JsonSchemaResolver
    {
        LoadedSchemas = {baseSchema}
    };

var derivedSchema = JsonSchema.Parse(@"
{
  ""$schema"": ""http://json-schema.org/draft-03/schema#"",
  ""id"": ""http://mycompany/derived-schema#"",
  ""type"": ""object"",

  ""extends"":{ ""$ref"": ""http://mycompany/base-schema#""},

  ""properties"": {
    ""lastName"": { ""type"": ""string"", ""required"": true}
  }
}
", resolver);

Скрипт: https://dotnetfiddle.net/g1nFew

person dcastro    schedule 26.05.2015

Я думаю, проблема может заключаться в том, что у вас есть относительные URI в этих элементах $ref, но нет свойств id для установления базового URI. Возможно, вы сможете решить свою проблему, добавив id="<absolute-url>"в самый внешний контекст, определяющий, откуда можно получить эти внешние файлы.

См. раздел 7 http://json-schema.org/latest/json-schema-core.html

P.S. Я заметил, что в вашем элементе measure у вас есть значения $ref и description. В черновике json-reference в Интернете говорится: Любые элементы, кроме "$ref" в объекте JSON Reference, ДОЛЖНЫ игнорироваться. Вероятно, это не приносит никакого вреда, но было бы удивительно, если бы кто-то ожидал, что это значение, чтобы переопределить описание во внешнем файле.

person Burt_Harris    schedule 17.07.2014
comment
Прошло некоторое время с тех пор, как я задал этот вопрос, но я почти уверен, что ответ заключается в том, что JSON.net не разрешает ссылки - вам нужно сделать это самостоятельно. Он БУДЕТ разрешать $ref из атрибута id, что является обходным путем, который я упомянул и реализовал. Я заметил в коде для jsonschema2pojo, что они сами разрешают ссылки, поэтому я создал похожая утилита для C#. - person sbl03; 04.08.2014