Я пытаюсь использовать библиотеку JsonSchema.Net для проверки объектов JSON.
Например, у меня есть следующие схемы: основная схема AddressChangedEvent.schema.json, которая ссылается как на EventHeader.schema.json, так и на AddressChangedEventBody.schema.json.
AddressChangedEvent.schema.json:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schemas.example.com/1.0/address ... event.json",
"title": "Address Changed Event",
"type": "object",
"additionalProperties": false,
"properties": {
"header": {
"$ref": "https://schemas.example.com/1.0/event-h ... chema.json"
},
"body": {
"$ref": "https://schemas.example.com/1.0/address ... chema.json"
}
},
"required": [ "header", "body" ]
}
EventHeader.schema.json:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schemas.example.com/1.0/event-h ... chema.json",
"title": "Event Header",
"type": "object",
"additionalProperties": false,
"properties": {
"messageId": {
"type": "string",
"minLength": 1
},
"messageType": {
"type": "string",
"minLength": 1
},
"version": {
"type": "string",
"minLength": 1
},
"utcSentDateTime": {
"type": "string",
"format": "date-time"
}
},
"required": [
"messageId",
"messageType",
"version",
"utcSentDateTime"
]
}
AddressChangedEventBody.schema.json:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schemas.example.com/1.0/address ... chema.json",
"title": "Address Changed Event Body",
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"type": "string",
"minLength": 1
},
"changedBy": {
"type": "string",
"minLength": 1
}
},
"required": [ "name", "changedBy" ]
}
Приложение записывает в базу данных событие AddressChangedEvent как JSON, поэтому я хочу проверить JSON перед записью в базу данных...
Проблема в том, что схемы, на которые ссылаются, не разрешаются во время проверки на соответствие схемам, несмотря на то, что они зарегистрированы в глобальном реестре.
У меня есть JsonSchemaProvider, который считывает все схемы JSON один раз и сохраняет их в реестре схем... но при проверке JSON Я получаю эту ошибку
Json.Schema.RefResolutionException
Не удалось разрешить «https://schemas.example.com/1.0/address ... chema.json»
Вот JsonSchemaProvider (зарегистрированный как синглтон):
public class JsonSchemaProvider : IJsonSchemaProvider
{
private static readonly ConcurrentDictionary RegisteredSchemaIds = new(StringComparer.Ordinal);
private readonly string _basePath;
private readonly ConcurrentDictionary _cache = new(StringComparer.OrdinalIgnoreCase);
public JsonSchemaProvider()
{
var coreAssembly = typeof(IJsonSchemaProvider).Assembly;
var location = Path.GetDirectoryName(coreAssembly.Location)!;
_basePath = Path.Combine(location, "Areas", "JsonSchemas");
if (!Directory.Exists(_basePath))
{
return;
}
foreach (var file in Directory.GetFiles(_basePath, "*.schema.json", SearchOption.AllDirectories))
{
var relativeKey = Path.GetRelativePath(_basePath, file).Replace('\\', '/');
var schema = LoadAndRegisterSchema(file);
_cache.TryAdd(relativeKey, schema);
}
}
public JsonSchema GetSchema(string fileName, string version)
{
var key = $"{version}/{fileName}";
if (_cache.TryGetValue(key, out var schema))
{
return schema;
}
var fullPath = Path.Combine(_basePath, version, fileName);
schema = LoadAndRegisterSchema(fullPath);
_cache[key] = schema;
return schema;
}
private static JsonSchema LoadAndRegisterSchema(string schemaFilePath)
{
var text = File.ReadAllText(schemaFilePath);
var schema = JsonSchema.FromText(File.ReadAllText(schemaFilePath));
using var doc = JsonDocument.Parse(text);
var id = doc.RootElement.TryGetProperty("$id", out var idProperty) &&
Uri.TryCreate(idProperty.GetString(), UriKind.Absolute, out var absoluteId)
? absoluteId
: new Uri(Path.GetFullPath(schemaFilePath));
if (RegisteredSchemaIds.TryAdd(id.ToString(), 0))
{
SchemaRegistry.Global.Register(id, schema);
}
return schema;
}
}
JsonSchemaValidator:
public class JsonSchemaValidator(IJsonSchemaProvider jsonSchemaProvider) : IJsonSchemaValidator
{
public bool TryValidate(string? json, string jsonSchemaFileName, string jsonSchemaVersion, out string errors)
{
ArgumentNullException.ThrowIfNull(json);
ArgumentException.ThrowIfNullOrWhiteSpace(jsonSchemaFileName);
ArgumentException.ThrowIfNullOrWhiteSpace(jsonSchemaVersion);
var schema = jsonSchemaProvider.GetSchema(jsonSchemaFileName, jsonSchemaVersion);
var jsonNode = JsonNode.Parse(json);
var targetNode = jsonNode;
return EvaluateNode(schema, targetNode!, out errors);
}
private static bool EvaluateNode(JsonSchema schema, JsonNode node, out string errors)
{
var evaluationOptions = new EvaluationOptions
{
OutputFormat = OutputFormat.Hierarchical
};
var result = schema.Evaluate(node, evaluationOptions);
if (result.IsValid)
{
errors = string.Empty;
return true;
}
var messages = ExtractErrors(result).ToArray();
errors = string.Join(',', messages);
return false;
}
private static IEnumerable ExtractErrors(EvaluationResults result)
{
if (result.Errors is not null)
{
foreach (var error in result.Errors)
{
yield return $"{result.InstanceLocation}: {error.Value}";
}
}
foreach (var detail in result.Details)
{
foreach (var message in ExtractErrors(detail))
{
yield return message;
}
}
}
}
ОБНОВЛЕНИЕ
Я заметил, что порядок загрузки схем имеет значение, порядок должен быть от наименее зависимой схемы к наиболее зависимой схеме...
if (buildParentSchemaLast) // The order of schema registration matters (doesn't throw RefResolutionException)
{
headerSchema = JsonSchema.FromText(File.ReadAllText("JsonSchemas/EventHeader.schema.json"));
bodySchema = JsonSchema.FromText(File.ReadAllText("JsonSchemas/AddressChangedEventBody.schema.json"));
parentSchema = JsonSchema.FromText(File.ReadAllText("JsonSchemas/AddressChangedEvent.schema.json"));
}
else // throws RefResolutionException
{
headerSchema = JsonSchema.FromText(File.ReadAllText("JsonSchemas/EventHeader.schema.json"));
parentSchema = JsonSchema.FromText(File.ReadAllText("JsonSchemas/AddressChangedEvent.schema.json"));
bodySchema = JsonSchema.FromText(File.ReadAllText("JsonSchemas/AddressChangedEventBody.schema.json"));
}
Подробнее здесь: https://stackoverflow.com/questions/798 ... other-sche
Использование JsonSchema.Net для проверки JSON, когда схема JSON ссылается на другие схемы. ⇐ C#
Место общения программистов C#
1765883241
Anonymous
Я пытаюсь использовать библиотеку JsonSchema.Net для проверки объектов JSON.
Например, у меня есть следующие схемы: основная схема AddressChangedEvent.schema.json, которая ссылается как на EventHeader.schema.json, так и на AddressChangedEventBody.schema.json.
AddressChangedEvent.schema.json:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schemas.example.com/1.0/address-changed-event.json",
"title": "Address Changed Event",
"type": "object",
"additionalProperties": false,
"properties": {
"header": {
"$ref": "https://schemas.example.com/1.0/event-header.schema.json"
},
"body": {
"$ref": "https://schemas.example.com/1.0/address-changed-event-body.schema.json"
}
},
"required": [ "header", "body" ]
}
EventHeader.schema.json:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schemas.example.com/1.0/event-header.schema.json",
"title": "Event Header",
"type": "object",
"additionalProperties": false,
"properties": {
"messageId": {
"type": "string",
"minLength": 1
},
"messageType": {
"type": "string",
"minLength": 1
},
"version": {
"type": "string",
"minLength": 1
},
"utcSentDateTime": {
"type": "string",
"format": "date-time"
}
},
"required": [
"messageId",
"messageType",
"version",
"utcSentDateTime"
]
}
AddressChangedEventBody.schema.json:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schemas.example.com/1.0/address-changed-event-body.schema.json",
"title": "Address Changed Event Body",
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"type": "string",
"minLength": 1
},
"changedBy": {
"type": "string",
"minLength": 1
}
},
"required": [ "name", "changedBy" ]
}
Приложение записывает в базу данных событие AddressChangedEvent как JSON, поэтому я хочу проверить JSON перед записью в базу данных...
Проблема в том, что схемы, на которые ссылаются, не разрешаются во время проверки на соответствие схемам, несмотря на то, что они зарегистрированы в глобальном реестре.
У меня есть JsonSchemaProvider, который считывает все схемы JSON один раз и сохраняет их в реестре схем... но при проверке JSON Я получаю эту ошибку
Json.Schema.RefResolutionException
Не удалось разрешить «https://schemas.example.com/1.0/address-changed-event-body.schema.json»
Вот JsonSchemaProvider (зарегистрированный как синглтон):
public class JsonSchemaProvider : IJsonSchemaProvider
{
private static readonly ConcurrentDictionary RegisteredSchemaIds = new(StringComparer.Ordinal);
private readonly string _basePath;
private readonly ConcurrentDictionary _cache = new(StringComparer.OrdinalIgnoreCase);
public JsonSchemaProvider()
{
var coreAssembly = typeof(IJsonSchemaProvider).Assembly;
var location = Path.GetDirectoryName(coreAssembly.Location)!;
_basePath = Path.Combine(location, "Areas", "JsonSchemas");
if (!Directory.Exists(_basePath))
{
return;
}
foreach (var file in Directory.GetFiles(_basePath, "*.schema.json", SearchOption.AllDirectories))
{
var relativeKey = Path.GetRelativePath(_basePath, file).Replace('\\', '/');
var schema = LoadAndRegisterSchema(file);
_cache.TryAdd(relativeKey, schema);
}
}
public JsonSchema GetSchema(string fileName, string version)
{
var key = $"{version}/{fileName}";
if (_cache.TryGetValue(key, out var schema))
{
return schema;
}
var fullPath = Path.Combine(_basePath, version, fileName);
schema = LoadAndRegisterSchema(fullPath);
_cache[key] = schema;
return schema;
}
private static JsonSchema LoadAndRegisterSchema(string schemaFilePath)
{
var text = File.ReadAllText(schemaFilePath);
var schema = JsonSchema.FromText(File.ReadAllText(schemaFilePath));
using var doc = JsonDocument.Parse(text);
var id = doc.RootElement.TryGetProperty("$id", out var idProperty) &&
Uri.TryCreate(idProperty.GetString(), UriKind.Absolute, out var absoluteId)
? absoluteId
: new Uri(Path.GetFullPath(schemaFilePath));
if (RegisteredSchemaIds.TryAdd(id.ToString(), 0))
{
SchemaRegistry.Global.Register(id, schema);
}
return schema;
}
}
JsonSchemaValidator:
public class JsonSchemaValidator(IJsonSchemaProvider jsonSchemaProvider) : IJsonSchemaValidator
{
public bool TryValidate(string? json, string jsonSchemaFileName, string jsonSchemaVersion, out string errors)
{
ArgumentNullException.ThrowIfNull(json);
ArgumentException.ThrowIfNullOrWhiteSpace(jsonSchemaFileName);
ArgumentException.ThrowIfNullOrWhiteSpace(jsonSchemaVersion);
var schema = jsonSchemaProvider.GetSchema(jsonSchemaFileName, jsonSchemaVersion);
var jsonNode = JsonNode.Parse(json);
var targetNode = jsonNode;
return EvaluateNode(schema, targetNode!, out errors);
}
private static bool EvaluateNode(JsonSchema schema, JsonNode node, out string errors)
{
var evaluationOptions = new EvaluationOptions
{
OutputFormat = OutputFormat.Hierarchical
};
var result = schema.Evaluate(node, evaluationOptions);
if (result.IsValid)
{
errors = string.Empty;
return true;
}
var messages = ExtractErrors(result).ToArray();
errors = string.Join(',', messages);
return false;
}
private static IEnumerable ExtractErrors(EvaluationResults result)
{
if (result.Errors is not null)
{
foreach (var error in result.Errors)
{
yield return $"{result.InstanceLocation}: {error.Value}";
}
}
foreach (var detail in result.Details)
{
foreach (var message in ExtractErrors(detail))
{
yield return message;
}
}
}
}
[b]ОБНОВЛЕНИЕ[/b]
Я заметил, что порядок загрузки схем имеет значение, порядок должен быть от наименее зависимой схемы к наиболее зависимой схеме...
if (buildParentSchemaLast) // The order of schema registration matters (doesn't throw RefResolutionException)
{
headerSchema = JsonSchema.FromText(File.ReadAllText("JsonSchemas/EventHeader.schema.json"));
bodySchema = JsonSchema.FromText(File.ReadAllText("JsonSchemas/AddressChangedEventBody.schema.json"));
parentSchema = JsonSchema.FromText(File.ReadAllText("JsonSchemas/AddressChangedEvent.schema.json"));
}
else // throws RefResolutionException
{
headerSchema = JsonSchema.FromText(File.ReadAllText("JsonSchemas/EventHeader.schema.json"));
parentSchema = JsonSchema.FromText(File.ReadAllText("JsonSchemas/AddressChangedEvent.schema.json"));
bodySchema = JsonSchema.FromText(File.ReadAllText("JsonSchemas/AddressChangedEventBody.schema.json"));
}
Подробнее здесь: [url]https://stackoverflow.com/questions/79848024/using-jsonschema-net-to-validate-json-when-the-json-schema-references-other-sche[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия