首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在$schema期间注入JSON $schema值

如何在$schema期间注入JSON $schema值
EN

Stack Overflow用户
提问于 2022-03-26 03:10:43
回答 1查看 302关注 0票数 0

我使用以下方法为我的C#代码创建了一个JSON模式:

代码语言:javascript
复制
// Create JSON schema
var generator = new JSchemaGenerator();
var schema = generator.Generate(typeof(ConfigFileJsonSchema));
schema.Title = "PlexCleaner Schema";
schema.Description = "PlexCleaner config file JSON schema";
schema.SchemaVersion = new Uri("http://json-schema.org/draft-06/schema");
schema.Id = new Uri("https://raw.githubusercontent.com/ptr727/PlexCleaner/main/PlexCleaner.schema.json");
Console.WriteLine(schema);

每当我从代码中创建JSON输出时,我都想添加对此方案的引用:

代码语言:javascript
复制
    private static string ToJson(ConfigFileJsonSchema settings)
    {
        return JsonConvert.SerializeObject(settings, Settings);
    }

    private static readonly JsonSerializerSettings Settings = new()
    {
        Formatting = Formatting.Indented,
        StringEscapeHandling = StringEscapeHandling.EscapeNonAscii,
        NullValueHandling = NullValueHandling.Ignore,
        // We expect containers to be cleared before deserializing
        // Make sure that collections are not read-only (get; set;) else deserialized values will be appended
        // https://stackoverflow.com/questions/35482896/clear-collections-before-adding-items-when-populating-existing-objects
        ObjectCreationHandling = ObjectCreationHandling.Replace
        // TODO: Add TraceWriter to log to Serilog
    };

如何以编程方式将$schema URI添加到创建的JSON中,不是指动态创建模式,而是如下所示:

代码语言:javascript
复制
public class ConfigFileJsonSchemaBase
{
    // Schema reference
    [JsonProperty(PropertyName = "$schema", Order = -2)]
    public string Schema { get; } = "https://raw.githubusercontent.com/ptr727/PlexCleaner/main/PlexCleaner.schema.json";

    // Default to 0 if no value specified, and always write the version first
    [DefaultValue(0)]
    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate, Order = -2)]
    public int SchemaVersion { get; set; } = ConfigFileJsonSchema.Version;
}

而不需要向类添加$schema条目。例如相当于:

代码语言:javascript
复制
schema.SchemaVersion = new Uri("http://json-schema.org/draft-06/schema");

还有一个类似的未回答的问题:json serialization to refer schema

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-03-26 11:06:48

您可以使用JsonConverter:

代码语言:javascript
复制
public class SchemaJsonConverter : JsonConverter
{
    private readonly string _schemaUrl;

    private readonly Type[] _types;

    public SchemaJsonConverter(string schemaUrl, params Type[] types)
    {
        this._schemaUrl = schemaUrl;
        this._types = types;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        JToken t = JToken.FromObject(value);

        if (t.Type != JTokenType.Object)
        {
            t.WriteTo(writer);
        }
        else
        {
            var o = (JObject)t;
            o.AddFirst(new JProperty("$Schema", this._schemaUrl));
            o.WriteTo(writer);
        }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException("Unnecessary because CanRead is false. The type will skip the converter.");
    }

    public override bool CanRead
    {
        get { return false; }
    }

    public override bool CanConvert(Type objectType)
    {
        return this._types.Any(t => t == objectType);
    }
}

您需要该类型来检查受转换器影响的类型,并需要模式url将其注入您的JSON中。转换器允许您对序列化过程进行精细控制。

我使用一个简单的类来测试转换器:

代码语言:javascript
复制
public class Something
{
    public int Integer { get; set; }
    public string Text { get; set; }
}

以及运行示例的方法:

代码语言:javascript
复制
public static void Test()
{
    var something = new Something
    {
        Integer = 37, 
        Text = "A text"
    };

    var settings = new JsonSerializerSettings
    {
        Formatting = Formatting.Indented,
        StringEscapeHandling = StringEscapeHandling.EscapeNonAscii,
        NullValueHandling = NullValueHandling.Ignore,
        // We expect containers to be cleared before deserializing
        // Make sure that collections are not read-only (get; set;) else deserialized values will be appended
        // https://stackoverflow.com/questions/35482896/clear-collections-before-adding-items-when-populating-existing-objects
        ObjectCreationHandling = ObjectCreationHandling.Replace
        // TODO: Add TraceWriter to log to Serilog
    };

    var schemaUrl = "http://json-schema.org/draft-06/schema";
    settings.Converters.Add(new SchemaJsonConverter(schemaUrl, something.GetType()));

    var json = JsonConvert.SerializeObject(something, settings);
    Console.WriteLine(json);
}

输出:

代码语言:javascript
复制
{
  "$Schema": "http://json-schema.org/draft-06/schema",
  "Integer": 37,
  "Text": "A text"
}

更新

用于序列化的静态方法:

代码语言:javascript
复制
public static string SerializeJson(object obj, JsonSerializerSettings settings, string schemaUrl = null)
{
    if (!string.IsNullOrEmpty(schemaUrl))
    {
        settings.Converters.Add(new SchemaJsonConverter(schemaUrl, obj.GetType()));
    }

    return JsonConvert.SerializeObject(obj, settings);
}

用法:

代码语言:javascript
复制
var json = SerializeJson(something, settings, schemaUrl);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71625019

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档