json_schema icon indicating copy to clipboard operation
json_schema copied to clipboard

Using relative file paths in refs

Open dcharkes opened this issue 11 months ago • 2 comments

Hey! I love this package, and I've been playing around with it to validate JSONs and schemas.

However, I can't seem to use relative paths in refs.

https://github.com/Workiva/json_schema/blob/dc39865f7849922af14e092c94d94805211c2207/lib/src/json_schema/json_schema.dart#L1963-L1967

It turns _SimpleUri (../../../hook/lib/schema/build_output.schema.json) into _Uri (/hook/lib/schema/build_output.schema.json).

I'm probably holding it wrong. (I don't have $ids for example, and these seem to be used in resolution.) I'm trying to reproduce the behavior I get with the default JSON editor in VSCode, but that seems to work with relative paths in schemas.

Repro:

https://github.com/dart-lang/native/blob/299b683e1c3a8224f2566d803e1431adc3bf37a7/pkgs/code_assets/test/schema/schema_test.dart#L25-L38

dcharkes avatar Feb 11 '25 17:02 dcharkes

Interactions between $ids and $refs can be difficult to reason about. Would it be possible for you to share a couple full example schemas where the problem occurs? It's hard to troubleshoot based on $refs alone. A minimum test case would be really helpful!

michaelcarter-wf avatar Feb 11 '25 18:02 michaelcarter-wf

Thanks for the quick reply! Here's a small repro.

pkgs/repro/lib/schema/base.schema.json

{
    "$schema": "https://json-schema.org/draft-07/schema#",
    "type": "object",
    "properties": {
        "some_int": {
            "type": "integer"
        }
    },
    "required": [
        "some_int"
    ]
}

pkgs/repro/lib/schema/extended.schema.json

{
    "$schema": "https://json-schema.org/draft-07/schema#",
    "allOf": [
        {
            "$ref": "base.schema.json#"
        }
    ],
    "properties": {
        "some_string": {
            "type": "string"
        }
    },
    "required": [
        "some_string"
    ]
}

pkgs/repro/test/data/data.json

{
    "$schema": "../../lib/schema/extended.schema.json",
    "some_int": 123
}

pkgs/repro/test/schema/schema_test.dart

import 'dart:convert';
import 'dart:io';

import 'package:json_schema/json_schema.dart';

void main() {
  final packageUri = Platform.script.resolve('../../');
  final schemasUri = packageUri.resolve('lib/schema/');

  final allSchemas = <Uri, Map<String, dynamic>>{};

  Directory.fromUri(schemasUri).listSync().forEach((file) {
    file as File;
    final json = jsonDecode(file.readAsStringSync());
    allSchemas[file.uri] = json;
  });

  final schemaUri = schemasUri.resolve('extended.schema.json');
  final schemaJson = allSchemas[schemaUri]!;

  final schema = JsonSchema.create(
    schemaJson,
    refProvider: RefProvider.sync((String ref) {
      print('ref: $ref');
      // Undoing ref mangling.
      // if (ref.startsWith('/')) {
      //   ref = ref.substring(1);
      // }
      final x = schemaUri.resolve(ref);
      return allSchemas[x]!;
    }),
  );

  final buildOutputUri = packageUri.resolve('test/data/data.json');
  final buildOutputJson = jsonDecode(
    File.fromUri(buildOutputUri).readAsStringSync(),
  );
  final result = schema.validate(buildOutputJson);
  print(result);
}

pkgs/repro/pubspec.yaml

name: repro

environment:
  sdk: '^3.7.0'

dev_dependencies:
  json_schema: ^5.2.0
  test: ^1.25.15

dcharkes avatar Feb 12 '25 08:02 dcharkes