How to reference external files with JSON.net?

2019-05-18 17:45发布

Here is the error I am getting when JSON.net is trying to read my JSON schema ( 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

My JSON schema:

{
  "$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."
    }
  },
}

My problem is that I have this JSON schema with this reference to an external file, data-result.json, but JSON.net does not yet know it exists. Is there some sort of fix for this? One idea I have is to skim through the schema, and if there are any references to external files, to parse those with a common JsonSchemaResolver. I'd have to add IDs as appropriate, since it looks like $ref likes to match by the ID, even though over at json-schema.org, there are clear examples of $ref being used with file names. I'd like to know if there is a better way that JSON.net natively supports referencing external schemas.

The source code is hosted on Github, if it helps. I have tested with the $ref field removed, and it compiles successfully.

3条回答
forever°为你锁心
2楼-- · 2019-05-18 17:53

Json.NET Schema has much improved support for resolving external references.

Read more here: http://www.newtonsoft.com/jsonschema/help/html/LoadingSchemas.htm

查看更多
爷、活的狠高调
3楼-- · 2019-05-18 17:54

One idea I have is to skim through the schema, and if there are any references to external files, to parse those with a common JsonSchemaResolver

Yes, you need to know which schemas your schema depends on, parse those first and add them to a JsonSchemaResolver. The schemas will be resolved using their IDs.

Here's an example (using draft-03 syntax):

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);

Fiddle: https://dotnetfiddle.net/g1nFew

查看更多
女痞
4楼-- · 2019-05-18 17:56

I think the problem may be that you have relative URI's in those $ref items, but no id properties to establish a base URI. You may be able to resolve your problem by adding id="<absolute-url>"in the outermost context establishing where those external files can be retrieved from.

See section 7 of http://json-schema.org/latest/json-schema-core.html

P.S. In your measure item, I notice you have both a $ref and description values. The json-reference internet draft says Any members other than "$ref" in a JSON Reference object SHALL be ignored. It probably doesn't do any harm, but could be surprising if someone was to expect that value to override the description in the external file.

查看更多
登录 后发表回答