【问题标题】:Custom deserialization with System.Text.Json使用 System.Text.Json 自定义反序列化
【发布时间】:2021-03-03 08:45:14
【问题描述】:

我的项目中有一个 JSON 字符串,例如:(来自 API 调用) (我也先搜索,但没有找到符合我的情况)

"
{
  "property": [
     {
       "property_1": 1,
       "property_2": true,
       "property_3": [
         {
           "property_3_1": 11,
           "property_3_2": "value_3_2_1",
           "property_3_3": true
         },
         {
           "property_3_1": 12,
           "property_3_2": "value_3_2_2",
           "property_3_3": false
         }
       ]
     },
     {
       "property_1": 2,
       "property_2": false,
       "property_3": [
         {
           "property_3_1": 21,
           "property_3_2": "value_3_2_2",
           "property_3_3": false
         },
         {
           "property_3_1": 22,
           "property_3_2": "value_3_2_2",
           "property_3_3": true
         }
       ]
     }
  ]
}
"

我需要将其反序列化为以下类的列表:

public class PropertyDto
{
    public long Property_1 { get; set; }

    public bool property_2 { get; set; }

    public string property_3 { get; set; }
}

有没有办法将“property_3”的数组反序列化为字符串? 类似:

var peroperty = new PropertyDto();

peroperty.Peroperty_3 = "
[
  {
    "property_3_1": 21,
    "property_3_2": "value_3_2",
    "property_3_3": false
  },
  {
    "property_3_1": 12,
    "property_3_2": "value_3_2_2",
    "property_3_3": false
  }
]
"

Asp.Net Core 5 | System.Text.Json

【问题讨论】:

  • 所以你想直接从 json 反序列化到 string[]?
  • @Dominik 我只想将“property_3”反序列化为字符串,而不是 C# 中的相关类结构
  • 我不清楚你打算如何工作。您有“property_1”,其中包含一个对象数组,子对象的“property_3”属性也包含一个对象数组,您似乎想以某种方式将其展平为您上面描述的 C# 模型。你能告诉我们(以人类的方式)它应该如何工作吗? Property_1Dto 应该是 Property_1Dto 的集合还是只有 1 个对象?
  • @SeyedArmanFatemi 您可以为您的用例编写自定义转换器:docs.microsoft.com/en-us/dotnet/standard/serialization/…
  • @John 结​​果应该是 Property_1Dto 的集合。我需要将 property_3 的内容作为字符串存储在每个项目中

标签: c# .net-core system.text.json


【解决方案1】:

您可以通过以下JsonConverter 实现此目的:

public class PropertyDtoConverter : JsonConverter<PropertyDto>
{
    public override PropertyDto? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType != JsonTokenType.StartObject)
        {
            throw new JsonException();
        }

        var dto = new PropertyDto();
        while (reader.Read())
        {
            if (reader.TokenType == JsonTokenType.EndObject)
            {
                return dto;
            }

            if (reader.TokenType == JsonTokenType.PropertyName)
            {
                string propName = (reader.GetString() ?? "").ToLower();
                reader.Read();

                switch (propName)
                {
                    case var _ when propName.Equals(nameof(PropertyDto.Property_1).ToLower()):
                        dto.Property_1 = reader.GetInt64();
                        break;
                    case var _ when propName.Equals(nameof(PropertyDto.Property_2).ToLower()):
                        dto.Property_2 = reader.GetBoolean();
                        break;
                    case var _ when propName.Equals(nameof(PropertyDto.Property_3).ToLower()):
                        if (JsonDocument.TryParseValue(ref reader, out JsonDocument jsonDoc))
                        {
                            dto.Property_3 = jsonDoc.RootElement.GetRawText();
                        }

                        break;
                }
            }
        }

        throw new JsonException();
    }

    public override void Write(Utf8JsonWriter writer, PropertyDto value, JsonSerializerOptions options)
    {
        writer.WriteStartObject();

        writer.WriteNumber(nameof(PropertyDto.Property_1), value.Property_1);
        writer.WriteBoolean(nameof(PropertyDto.Property_2), value.Property_2);
        writer.WriteString(nameof(PropertyDto.Property_3), value.Property_3);

        writer.WriteEndObject();
    }
}

模型类将变为:

[JsonConverter(typeof(PropertyDtoConverter))]
public class PropertyDto
{
    public long Property_1 { get; set; }

    public bool Property_2 { get; set; }
    
    public string Property_3 { get; set; }
}

您可以将字符串显式转换为PropertyDto:

PropertyDto dto = JsonSerializer.Deserialize<PropertyDto>(dtoString);

或隐含在控制器动作中:

[HttpPost]
public void Post(PropertyDto dto)
{
    ...
}

如果你想反序列化PropertyDto的整个集合,你可以这样做:

public class PropertyCollectionDto
{
    public List<PropertyDto> Property { get; set; } = new();
}

[HttpPost("/collection")]
public void Post(PropertyCollectionDto dto)
{
   ...
}

【讨论】:

  • 太棒了,谢谢。你为我节省了大量时间!
猜你喜欢
  • 1970-01-01
  • 2021-12-08
  • 2021-12-30
  • 2020-03-24
  • 2021-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-20
相关资源
最近更新 更多