System.Text.Json-将嵌套对象反序列化为字符串 [英] System.Text.Json - Deserialize nested object as string

查看:806
本文介绍了System.Text.Json-将嵌套对象反序列化为字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 System.Text.Json.JsonSerializer 部分反序列化模型,因此其中一个属性被读取为包含原始JSON的字符串

  public class SomeModel 
{
public int Id {get;。组; }
公共字符串Name {get;组; }
公用字串Info {get;组; }
}

示例代码

  var json = @ {
Id:1,
Name: Some Name,
信息:{
附加:字段,
Are:内部
}
} ;

var模型= JsonSerializer.Deserialize< SomeModel>(json);

应生成模型,该模型具有 Info 属性包含原始JSON的Info对象作为字符串:

  {
Additional: Fields,
是:内部
}

并抛出异常:


System.Text.Json.JsonException:---> System.InvalidOperationException:
不能获得令牌类型'StartObject'的值作为字符串。


到目前为止我已经尝试了什么:

 公共类InfoToStringConverter:JsonConverter< string> 
{
公共替代字符串Read(
ref Utf8JsonReader reader,Type type,JsonSerializerOptions options)
{
return reader.GetString();
}

公共重写void Write(
Utf8JsonWriter writer,string value,JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}

并将其应用到模型中

  [JsonConverter(typeof(InfoToStringConverter))] 
公共字符串Info {get;组; }

并将选项添加到 JsonSerializer

  var options = new JsonSerializerOptions(); 
options.Converters.Add(new InfoToStringConverter());
var模型= JsonSerializer.Deserialize< SomeModel>(json,选项);

仍然,它会抛出相同的异常:



< blockquote>

System.Text.Json.JsonException:---> System.InvalidOperationException:
无法获取令牌类型'StartObject'的值作为字符串。


什么才是我需要的正确食谱?它使用 Newtonsoft.Json 以类似的方式工作。



更新



对我来说,保持嵌套JSON对象尽可能原始很重要。因此,我避免使用像反序列化为 Dictionary 并进行序列化的选项,因为我担心会引入不必要的更改。

解决方案

找到了一种正确方法来正确读取 JsonConverter 中的嵌套JSON对象。完整的解决方案如下:

 公共类SomeModel 
{
public int Id {get;组; }

公共字符串Name {get;组; }

[JsonConverter(typeof(InfoToStringConverter))]
公共字符串Info {get;组; }
}

公共类InfoToStringConverter:JsonConverter< string>
{
公共替代字符串Read(
ref Utf8JsonReader reader,type typeToConvert,JsonSerializerOptions options)
{
using(var jsonDoc = JsonDocument.ParseValue(ref reader))
{
return jsonDoc.RootElement.GetRawText();
}
}

公共重写void Write(
Utf8JsonWriter writer,string value,JsonSerializerOptions options)
{
抛出new NotImplementedException() ;
}
}

在代码本身中甚至不需要创建选项:

  var json = @ {
Id:1,
Name: Some Name,
Info:{
Additional: Fields,
Are:内部
}
};

var模型= JsonSerializer.Deserialize< SomeModel>(json);

Info 属性中的原始JSON文本



并且没有混合模型表示形式及其序列化,如@PavelAnikhouski在回答中所述。

I'm trying to use the System.Text.Json.JsonSerializer to deserialize the model partially, so one of the properties is read as string that contains the original JSON.

public class SomeModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Info { get; set; }
}

The example code

var json = @"{
                 ""Id"": 1,
                 ""Name"": ""Some Name"",
                 ""Info"": {
                     ""Additional"": ""Fields"",
                     ""Are"": ""Inside""
                 }
             }";

var model = JsonSerializer.Deserialize<SomeModel>(json);

should produce the model, which Info property contains the Info object from the original JSON as string:

{
    "Additional": "Fields",
    "Are": "Inside"
}

It doesn't work out of the box and throws an exception:

System.Text.Json.JsonException: ---> System.InvalidOperationException: Cannot get the value of a token type 'StartObject' as a string.

What have I tried so far:

public class InfoToStringConverter : JsonConverter<string>
{
    public override string Read(
        ref Utf8JsonReader reader, Type type, JsonSerializerOptions options)
    {
        return reader.GetString();
    }

    public override void Write(
        Utf8JsonWriter writer, string value, JsonSerializerOptions options)
    {
        throw new NotImplementedException();
    }
}

and apply it in the model as

[JsonConverter(typeof(InfoToStringConverter))]
public string Info { get; set; }

and add in the options to JsonSerializer

var options = new JsonSerializerOptions();
options.Converters.Add(new InfoToStringConverter());
var model = JsonSerializer.Deserialize<SomeModel>(json, options);

Still, it throws the same exception:

System.Text.Json.JsonException: ---> System.InvalidOperationException: Cannot get the value of a token type 'StartObject' as a string.

What is the right recipe to cook what I need? It worked in a similar way using Newtonsoft.Json.

Update

For me it is important to keep the nested JSON object as original as possible. So, I'd avoid options like to deserialize as Dictionary and serialize back, because I'm afraid to introduce undesirable changes.

解决方案

Found a right way how to correctly read the nested JSON object inside the JsonConverter. The complete solution is the following:

public class SomeModel
{
    public int Id { get; set; }

    public string Name { get; set; }

    [JsonConverter(typeof(InfoToStringConverter))]
    public string Info { get; set; }
}

public class InfoToStringConverter : JsonConverter<string>
{
    public override string Read(
        ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        using (var jsonDoc = JsonDocument.ParseValue(ref reader))
        {
            return jsonDoc.RootElement.GetRawText();
        }
    }

    public override void Write(
        Utf8JsonWriter writer, string value, JsonSerializerOptions options)
    {
        throw new NotImplementedException();
    }
}

In the code itself there is no need even to create options:

var json = @"{
                 ""Id"": 1,
                 ""Name"": ""Some Name"",
                 ""Info"": {
                     ""Additional"": ""Fields"",
                     ""Are"": ""Inside""
                 }
             }";

var model = JsonSerializer.Deserialize<SomeModel>(json);

The raw JSON text in the Info property contains even extra spaces introduced in the example for nice readability.

And there is no mixing of model representation and its serialization as remarked @PavelAnikhouski in his answer.

这篇关于System.Text.Json-将嵌套对象反序列化为字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆