首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Manatee.Json内核3中序列化.NET

在Manatee.Json内核3中序列化.NET
EN

Stack Overflow用户
提问于 2020-01-22 08:22:22
回答 1查看 585关注 0票数 0

背景

我想从我的JsonSchema核心3应用程序中提供一些.NET,以及序列化成JSON的其他对象。由于Manatee.Json经常被更新,并且提供了对JsonSchema的良好支持,所以它们是我的首选。同时,JSON 3为返回具有魔力的对象提供了极好的支持,这些对象可以将对象转换为.NET文档。

示例:

代码语言:javascript
复制
public ActionResult<MyFancyClass> MyFancyAction()
{
    return new MyFancyClass {
        Property1 = "property 1 content",
        Property2 = "property 2 content",
    };
}

输出:

代码语言:javascript
复制
{
    "Property1": "property 1 content",
    "Property2": "property 2 content"
}

问题

JSON 3有对.NET的内部支持,它的System.Text.Json在前面的示例中使用。如果我尝试序列化Manatee.Json.Schema.JsonSchema,它的内部结构是序列化的,而不是json模式本身。

示例:

代码语言:javascript
复制
public ActionResult<MyFancyClass2> MyFancyAction2()
{
    return new MyFancyClass2 {
        Property1 = "property 1 content",
        Property1Schema = new JsonSchema()
            .Type(JsonSchemaType.String)
    };
}

输出:

代码语言:javascript
复制
{
  "Property1": "property 1 content",
  "Property1Schema": [{
    "name":"type",
    "supportedVersions":15,
    "validationSequence":1,
    "vocabulary": {
      "id":"https://json-schema.org/draft/2019-09/vocab/validation",
      "metaSchemaId":"https://json-schema.org/draft/2019-09/meta/validation"
    }
  }]
}

我希望这样做:

代码语言:javascript
复制
{
  "Property1": "property 1 content",
  "Property1Schema": {
    "type": "string",
  }
}

Manatee.Json.JsonValue还有一个相互冲突的内部结构,其中System.Text.Json.JsonSerializer无法正确访问内部get方法,例如,我得到了以下异常消息:

代码语言:javascript
复制
Cannot access value of type Object as type Boolean.

Discovery

Manatee.Json.Schema.JsonSchema有一个.ToJson()方法,可以用来作为JsonValue获得正确的json模式,但是接下来我遇到了序列化Manatee.Json.JsonValue时提到的问题。

问题

有人知道如何使System.Text.Json序列化Manatee.Json结构吗?

Sidemark

另一种方法是完全取代System.Text.Json (看看)。

EN

回答 1

Stack Overflow用户

发布于 2020-01-22 08:22:22

.NET Core3JSON序列化提供了许多配置选项。其中之一是添加转换器,这些转换器指定应该如何序列化不同类型。向前发展的一种方法是为JsonSchema创建一个JsonSchema,为JsonValue创建另一个。

对于JsonSchema,我们可以实现一个JsonSchemaConverter,在序列化/写入时,将json模式提取为JsonValue,并要求序列化程序将该JsonValue序列化。如下所示:

代码语言:javascript
复制
public class JsonSchemaConverter : JsonConverter<JsonSchema>
{
    public JsonSchemaConverter()
    {
        _manateeSerializer = new ManateeSerializer();
    }

    private ManateeSerializer _manateeSerializer { get; set; }

    public override JsonSchema Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var jsonText = reader.GetString();
        var jsonValue = JsonValue.Parse(jsonText);
        return _manateeSerializer.Deserialize<JsonSchema>(jsonValue);
    }

    public override void Write(Utf8JsonWriter writer, JsonSchema value, JsonSerializerOptions options)
    {
        var schemaAsJson = value.ToJson(_manateeSerializer);
        try
        {
            System.Text.Json.JsonSerializer.Serialize<JsonValue>(writer, schemaAsJson, options);
        }
        catch (Exception e)
        {
            Log.Information($"Failed to serialize JsonSchema ({e.Message});");
            writer.WriteNullValue();
        }
    }
}

对于JsonValue,我们可以将其转换为System.Text.Json理解的内容,因为它毕竟是json。一种不幸的方法是将JsonValue序列化为string,例如用JsonDocument.Parse(string)解析它并序列化它的RootElement属性。如果有人找到了更好的解决方案,那就太棒了!可能的实现可以如下所示:

代码语言:javascript
复制
public class JsonValueConverter : JsonConverter<JsonValue>
{
    public override JsonValue Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var json = reader.GetString();
        return JsonValue.Parse(json);
    }

    public override void Write(Utf8JsonWriter writer, JsonValue value, JsonSerializerOptions options)
    {
        string content = value.ToString();
        try
        {
            var jsonDocument = JsonDocument.Parse(content);
            JsonSerializer.Serialize<JsonElement>(writer, jsonDocument.RootElement, options);
        }
        catch (Exception e)
        {
            Log.Warning($"JsonDocument.Parse(JsonValue) failed in JsonValueConverter.Write(,,).\n{e.Message}");
            writer.WriteNullValue();
        }
    }
}

他们必须在Startup.cs注册如下:

代码语言:javascript
复制
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()
        .AddJsonOptions(options =>
        {
            options.JsonSerializerOptions.Converters.Add(new JsonValueConverter());
            options.JsonSerializerOptions.Converters.Add(new JsonSchemaConverter());
        });
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59855362

复制
相关文章

相似问题

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