如何在.NET 8中用System.Text.Json反序列化键不同结构相同的对象?
在.NET 8中使用System.Text.Json将字典结构的Cart反序列化为集合
问题描述
给定的JSON数据中,cart字段是一个以商品ID为键、商品详情为值的字典结构,需要将其反序列化为包含CartItem数组的Cart类结构,目标C#类定义大致如下,需用.NET 8的System.Text.Json.Serialization实现该反序列化。
示例JSON
{"checksum": "8ea325b368df5f2994e3c6da022e52db","totalPrice": {"amount": "71.98","symbol": "$","code": "USD","isZero": false,"rawAmount": 7198,"formattedAmount": "71.98","full": "$ 71.98","for_email": "$ 71.98"},"cart": {"1345516108": {"id": 1345516108,"price": {"currency": "USD","amount": "11.99","baseAmount": "29.99","finalAmount": "11.99","isDiscounted": true,"discountPercentage": 60,"discountDifference": "18.00","symbol": "$","isFree": false,"discount": 60,"isBonusStoreCreditIncluded": false,"bonusStoreCreditAmount": "0.00","promoId": "weekly_deals_3_november"},"timeAdded": 1700141748,"availability": {"isAvailable": true,"isAvailableInAccount": true},"isDiscounted": true,"isInDevelopment": false,"releaseDate": 1659560400,"salesVisibility": {"isActive": true,"fromObject": {"date": "2022-08-04 19:55:00.000000","timezone_type": 3,"timezone": "Europe/Nicosia"},"from": 1659632100,"toObject": {"date": "2037-12-31 23:59:59.000000","timezone_type": 3,"timezone": "Europe/Nicosia"},"to": 2145909599},"buyable": true,"title": "Hard West 2","url": "/en/game/hard_west_2","supportUrl": "/support/","forumUrl": null,"worksOn": {"Windows": true,"Mac": false,"Linux": false},"category": "Role-playing","originalCategory": null,"rating": 0,"type": 1,"isComingSoon": false,"isPriceVisible": true,"isMovie": false,"isGame": true,"slug": null,"isWishlistable": true,"extraInfo": [],"ageLimit": 0},"1456460669": {"id": 1456460669,"price": {"currency": "USD","amount": "59.99","baseAmount": "59.99","finalAmount": "59.99","isDiscounted": false,"discountPercentage": 0,"discountDifference": "0.00","symbol": "$","isFree": false,"discount": 0,"isBonusStoreCreditIncluded": false,"bonusStoreCreditAmount": "0.00","promoId": null},"timeAdded": 1700141758,"availability": {"isAvailable": true,"isAvailableInAccount": true},"isDiscounted": false,"isInDevelopment": false,"releaseDate": 1691010000,"salesVisibility": {"isActive": true,"fromObject": {"date": "2020-10-06 19:50:00.000000","timezone_type": 3,"timezone": "Europe/Nicosia"},"from": 1602003000,"toObject": {"date": "2037-12-31 23:59:59.000000","timezone_type": 3,"timezone": "Europe/Nicosia"},"to": 2145909599},"buyable": true,"title": "Baldur's Gate 3","url": "/en/game/baldurs_gate_iii","supportUrl": "/support/","forumUrl": null,"worksOn": {"Windows": true,"Mac": true,"Linux": false},"category": "Role-playing","originalCategory": null,"rating": 39,"type": 1,"isComingSoon": false,"isPriceVisible": true,"isMovie": false,"isGame": true,"slug": null,"isWishlistable": true,"extraInfo": [],"ageLimit": 0}},"overallAgeLimit": 0}
目标C#类结构
public class Rootobject { public string checksum { get; set; } public Totalprice totalPrice { get; set; } public Cart cart { get; set; } public int overallAgeLimit { get; set; } } public class Totalprice { public string amount { get; set; } public string symbol { get; set; } public string code { get; set; } public bool isZero { get; set; } public int rawAmount { get; set; } public string formattedAmount { get; set; } public string full { get; set; } public string for_email { get; set; } } public class Cart { public CartItem[] cartItems { get; set; } } public class CartItem { public int id { get; set; } public Price price { get; set; } public int timeAdded { get; set; } public Availability availability { get; set; } public bool isDiscounted { get; set; } public bool isInDevelopment { get; set; } public int releaseDate { get; set; } public SalesVisibility salesVisibility { get; set; } public bool buyable { get; set; } public string title { get; set; } public string url { get; set; } public string supportUrl { get; set; } public string forumUrl { get; set; } public WorksOn worksOn { get; set; } public string category { get; set; } public object originalCategory { get; set; } public int rating { get; set; } public int type { get; set; } public bool isComingSoon { get; set; } public bool isPriceVisible { get; set; } public bool isMovie { get; set; } public bool isGame { get; set; } public object slug { get; set; } public bool isWishlistable { get; set; } public object[] extraInfo { get; set; } public int ageLimit { get; set; } } public class Price { public string currency { get; set; } public string amount { get; set; } public string baseAmount { get; set; } public string finalAmount { get; set; } public bool isDiscounted { get; set; } public int discountPercentage { get; set; } public string discountDifference { get; set; } public string symbol { get; set; } public bool isFree { get; set; } public int discount { get; set; } public bool isBonusStoreCreditIncluded { get; set; } public string bonusStoreCreditAmount { get; set; } public string promoId { get; set; } } public class Availability { public bool isAvailable { get; set; } public bool isAvailableInAccount { get; set; } } public class SalesVisibility { public bool isActive { get; set; } public FromObject fromObject { get; set; } public int from { get; set; } public ToObject toObject { get; set; } public int to { get; set; } } public class FromObject { public string date { get; set; } public int timezone_type { get; set; } public string timezone { get; set; } } public class ToObject { public string date { get; set; } public int timezone_type { get; set; } public string timezone { get; set; } } public class WorksOn { public bool Windows { get; set; } public bool Mac { get; set; } public bool Linux { get; set; } }
解决方案
可以通过自定义Json转换器实现该需求,具体步骤如下:
1. 创建自定义Cart转换器
实现JsonConverter<Cart>,在反序列化时将JSON中的字典结构转为CartItem数组:
public class CartConverter : JsonConverter<Cart> { public override Cart Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 将JSON中的cart对象反序列化为字典 var cartDictionary = JsonSerializer.Deserialize<Dictionary<string, CartItem>>(ref reader, options); // 将字典的值转为数组并返回Cart实例 return new Cart { cartItems = cartDictionary?.Values.ToArray() ?? Array.Empty<CartItem>() }; } public override void Write(Utf8JsonWriter writer, Cart value, JsonSerializerOptions options) { // 如果需要序列化,可将数组转回字典(以CartItem.Id为键) var cartDictionary = value.cartItems?.ToDictionary(item => item.id.ToString()) ?? new Dictionary<string, CartItem>(); JsonSerializer.Serialize(writer, cartDictionary, options); } }
2. 为Cart类添加转换器特性
在Cart类上标记[JsonConverter]特性,指定使用自定义转换器:
[JsonConverter(typeof(CartConverter))] public class Cart { public CartItem[] cartItems { get; set; } }
3. 执行反序列化
使用JsonSerializer.Deserialize方法完成反序列化:
string json = "你的JSON字符串"; var root = JsonSerializer.Deserialize<Rootobject>(json);
此时root.cart.cartItems将包含JSON中cart字段下的所有商品项。
内容的提问来源于stack exchange,提问作者Onur Buyukcaglar
相关产品推荐
相关产品推荐

