Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Local references don't work correctly #415

Closed
faldor20 opened this issue Mar 24, 2023 · 7 comments · Fixed by #423
Closed

Local references don't work correctly #415

faldor20 opened this issue Mar 24, 2023 · 7 comments · Fixed by #423
Labels
bug Something isn't working pkg:schema

Comments

@faldor20
Copy link

faldor20 commented Mar 24, 2023

Environment

  • Nuget Package: JsonSchema.Net
  • Nuget Version: 4.0.0
  • OS: Windows
  • .Net Target: net6.0

Describe the bug
When referencing schemas locally from inside a AllOf /OneOf/AnyOf block the reference isn't resolved against the baseUri of that schema

To Reproduce
Load all the json schema with their full path:

/// <summary>
/// Loads schema files into the global schema registry so they can be referenced later
/// </summary>
public void LoadSchemas(string repoPath)
{
    _logger.LogInformation("Loading Schemas");
    repoPath = Path.GetFullPath(repoPath);
    string[] files = Directory.GetFiles(repoPath, "*.json", SearchOption.AllDirectories);
    foreach(var file in files)
    {
        try
        {
            // _logger.LogDebug("Trying to load potential json schema: {File}",file);
            var schema = JsonSchema.FromFile(file);
            schema.BaseUri = new Uri(file);
            SchemaRegistry.Global.Register(schema);
        }
        catch (Exception a)
        {
            _logger.LogWarning("couldn't load schema {Error}", a);
        }
    }
}

then evaluate a file with a local reference eg:

{
  "$schema": "http://json-schema.org/draft-06/schema#",
  "type": "object",
  "allOf": [
    {
      "required": [
        "providerCode"
      ],
      "properties": {
        "providerCode": {
          "type": "string"
        }
      }
    },
    {
      "$ref": "b.json"
    }
  ],
  "unevaluatedProperties": false
}

The ref attempts to resolve ""https://json-everything.net/y984i8rniyfr/b.json". This is because because the scope was changed to a randomly generated one when entering het AllOf block "

Expected behavior
The ref should resolve and evaluate correctly based on the baseUrl

Additional context

I'm not entirely sure if this is actually within spec for jsonschema, but it certainly seems to be how all the other validators I've used work

@faldor20 faldor20 added the bug Something isn't working label Mar 24, 2023
@faldor20
Copy link
Author

Is the issue that promped creating #414

@gregsdennis
Copy link
Owner

gregsdennis commented Mar 24, 2023

The issue is that the schema needs to be initialized. This copies the base URI to all of the subschemas that don't define their own base URI (via $id).

Instead of

schema.BaseUri = new Uri(file);
SchemaRegistry.Global.Register(schema);

use

 SchemaRegistry.Global.Register(new Uri(file), schema);

This is what I do in the test suite to load files.

foreach (var fileName in fileNames)
{
var schema = JsonSchema.FromFile(fileName);
var uri = new Uri(fileName.Replace(remotesPath, "http://localhost:1234").Replace('\\', '/'));
SchemaRegistry.Global.Register(uri, schema);
}

This will properly initialize the schema which sets the base URI throughout the schema components. Not sure why what you're doing isn't working. I can look into that.

The other thing you can do (which might actually be preferred) is to add $id to all your schemas.

@gregsdennis
Copy link
Owner

Another thing to consider is that when you're using .FromFile() you don't need to set the base URI. The method does that for you.

@faldor20
Copy link
Author

faldor20 commented Mar 27, 2023

Okay thankyou. I tried what you suggested and it did indeed fix it so long as no schema with a $id references one without. If that happens the reference cannot be followed because the basePath is that of the $id not of the actual filepath.
Though it does seem that all the schemas get registered with both their ID path and absoluteFilePath.

Would it be worth checking for refs with the id and then if it's not found falling back to checking with the filepath as the basepath?

@gregsdennis
Copy link
Owner

The file path is already set as the base URI when you load it from the file. If it has an $id it overwrites the base URI with that value. There is no fallback.

@faldor20
Copy link
Author

I understand that there isn't one now but it might be nice to have an option to enable that in case your schema references a schema with a local path that either doesn't have a $id or has a different prefix in its $id

@gregsdennis
Copy link
Owner

or has a different prefix in its $id

Overriding $id is not something that I will support. You can register a schema with an alternate ID if you like so that it can be referenced with that alternate, but the $id keyword is king and will always set a schema's base URI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working pkg:schema
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants