Can't get JSON.NET Schema to find my externally referenced JSON schema files

1

I'm trying to validate the output of some REST Web API functions I've created against a third-party provided JSON schema. I'm using a .NET 4.8 console app to do the validation.

I'm using JSON.NET Schema (v3.0.0), and have been struggling with this problem here: my project-response.json schema file looks something like this:

{
  "$id": "http://www.whereever.com/services/projects/project-response.json",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "description": "project response definition",
  "type": "object",
  "properties": {
    ....
    "lead": {
      "description": "The lead person",
      "$ref": "common-types.json#/definitions/personType"
    },
    ....
  }
}

Among other things, it contains references to the common-types.json file in the same directory, that defines some basic types used by various parts of the schema - something like this:

{
  "$id": "http://www.whereever.com/services/projects/common-types.json",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "description": "common type definitions",
  "definitions": {
     ....
    "personType": {
      "type": "object",
      "properties": {
        "firstname": {
          "type": "string",
          "minLength": 1,
          "maxLength": 64
        },
        "lastname": {
          "type": "string",
          "minLength": 1,
          "maxLength": 64
        },
        "email": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256
        }
      },
      "required": [
        "firstname",
        "lastname"
      ]
    }, 
    

I get a JSON string as the response from API call, and I'd like to validate this JSON against this schema. I have tried to do it like this:

public bool Validate(string jsonData)
{
    string jsonSchemaFileName = Path.Combine(_schemaBaseDirectory, "project-response.json");
    
    // define a Json Text Reader for the schema
    using (StreamReader schemaFile = File.OpenText(jsonSchemaFileName))
    using (JsonTextReader reader = new JsonTextReader(schemaFile))
    {
        JSchemaUrlResolver resolver = new JSchemaUrlResolver();

        JSchemaReaderSettings settings = new JSchemaReaderSettings
                                                 {
                                                     Resolver = resolver,
                                                     BaseUri = new Uri(jsonSchemaFileName)
                                                 };

        JSchema schema = JSchema.Load(jsonReader, settings);

        // validate
        JToken jsonToken = JObject.Parse(jsonData);

        bool isValid = jsonToken.IsValid(schema, out IList<string> errors);

        return isValid;
    }
}

I was expecting that the JSON.NET Schema system would be able to now read the common-types.json from the same location where the project-response.json is located and look up the definitions in that common file - but alas, on the line

JSchema schema = JSchema.Load(jsonReader, settings);

I keep getting an error:

Newtonsoft.Json.Schema.JSchemaReaderException
HResult=0x80131500
Message=Error when resolving schema reference 'common-types.json#/definitions/projectIdType'. Path 'properties.id', line 7, position 11.

Source=Newtonsoft.Json.Schema

StackTrace:
at Newtonsoft.Json.Schema.Infrastructure.JSchemaReader.ResolveDeferedSchema(DeferedSchema deferedSchema) at Newtonsoft.Json.Schema.Infrastructure.JSchemaReader.ResolveDeferedSchemas() at Newtonsoft.Json.Schema.Infrastructure.JSchemaReader.ReadRoot(JsonReader reader, Boolean resolveDeferedSchemas) at Newtonsoft.Json.Schema.JSchema.Load(JsonReader reader, JSchemaReaderSettings settings)

Inner Exception 1:
WebException: The remote server returned an error: (404) Not Found.

Any ideas why this fails? Have I missed something crucial?

c#
json
json.net
jsonschema
asked on Stack Overflow Jul 13, 2020 by marc_s

1 Answer

2

You will need to remove $id, from project-response.json because it will define the base url for $ref. See this link. Or use JSchemaPreloadedResolver to preload the common-types.json like

JSchemaPreloadedResolver resolver = new JSchemaPreloadedResolver();
using(var commontypes = File.Open(jsonSchemaCommonTypeFileName, FileMode.Open))
{
    resolver.Add(new Uri("http://www.whereever.com/services/projects/common-types.json"), commontypes);
}
answered on Stack Overflow Jul 13, 2020 by Thinh Tran • edited Jul 13, 2020 by Thinh Tran

User contributions licensed under CC BY-SA 3.0