翼度科技»论坛 编程开发 .net 查看内容

System.Text.Json匿名对象反序列化

10

主题

10

帖子

30

积分

新手上路

Rank: 1

积分
30
以前就是一直使用 Newtonsoft.Json 用起来还是挺舒服的。由于 JSON 的应用越来越广,现在. NET Core 都内置了 System.Text.Json 可以直接对 JSON 进行操作,不过两个东西的体验依然有点区别。
有时候我们会遇到的从第三方传递过来的 json string 对象,对其进行解析并不需要所有的字段,只需要一个目标的字段时,可以考虑使用匿名对象/动态对象对其反序列化。
之前的 Newtonsoft.Json 好像直接使用 dynamic,运用 JObject 进行处理,现在的不是那么容易。下文代码基于. NET 6,为了代码整洁,实际配置了 PropertyNameCaseInsensitive = true,但是下面代码中并没有体现。
数据

我们定义了如下的类型,并从 OData 获得了 str 字符串型数据。
  1.         public readonly static string str = """
  2.         {"@odata.context":"http://localhost:9000/api/v1/$metadata#DataDto","value":[{"id":"0b734ed7-2955-4af4-a902-35dc17871094","timestamp":1684839865920},{"id":"7e285d08-cdb3-4209-8335-0ff9b20d39ef","timestamp":1684836312421}]}
  3.         """;
  4.     public class DataDto
  5.     {
  6.         public string? Id { get; set; }
  7.         public long Timestamp { get; set; }
  8.     }
复制代码
由于有元数据,我们无法直接将上面的字符串反序列化为 DataDto 的列表对象。
自定义类

最简单的方式,是对应此类对象,设计一个只用于反序列化的新类。
  1.     public class ODataEnumerableResultWrapper<T>
  2.         where T : class
  3.     {
  4.         public IEnumerable<T> Value { get; set; }
  5.     }
  6.         var meta = JsonSerializer.Deserialize<ODataEnumerableResultWrapper<DataDto>>(str);
  7.         var target = meta.Value;
复制代码
匿名方式

可以使用 JsonNode 来直接反序列化,并使用类似键值对的形式访问。
  1.     public static void Main() {
  2.         JsonNode? meta = JsonSerializer.Deserialize<JsonNode>(str);
  3.         //如果直接是简单的对象,而不是数组,可以使用GetValue<T>这种形式。
  4.         var count = meta?["value"]?.Deserialize<IEnumerable<DataDto>>().Count();
  5.         Console.WriteLine(count);
  6.     }
  7. }
复制代码
注意,这样的操作和你反序列化为 JsonDocument/JsonElement 并没有什么本质的区别。
动态方式

由于设计区别,直接使用 dynamic 进行反序列化,得到的对象并不具有一般 dynamic 的性质(实际上是 System.Text.Json.JsonElement 对象)。因此,我们无法通过的 dynamic 访问成员的形式进行操作。
  1. dynamic meta = JsonSerializer.Deserialize<dynamic>(str);
  2. Console.WriteLine(meta.GetType());
  3. //OUTPUT: System.Text.Json.JsonElement
复制代码
文章 说可以使用 ExpandoOject 实现,但是实际上无法对子级对象进行类似的访问,因为获取的子级对象,实际上是 JsonElement。
  1.         dynamic meta = JsonSerializer.Deserialize<System.Dynamic.ExpandoObject>(str);
  2.         Console.WriteLine(meta.GetType());
  3.         //System.Dynamic.ExpandoObject
  4.         Console.WriteLine(meta.value);
  5.         //[{"id":"0b734ed7-2955-4af4-a902-35dc17871094","timestamp":1684839865920},{"id":"7e285d08-cdb3-4209-8335-0ff9b20d39ef","timestamp":1684836312421}]
  6.         Console.WriteLine(meta.value.GetType());
  7.         //System.Text.Json.JsonElement
复制代码
当然可以通过自定义序列化的方式操作(见参考),但是这个办法与我们的不写额外代码的初衷相冲突,因此不考虑了。
参考


来源:https://www.cnblogs.com/podolski/archive/2023/05/23/17426371.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具