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?
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);
}
User contributions licensed under CC BY-SA 3.0