c# - 将 JSON 对象反序列化为嵌套的 C# 对象
问题描述
编辑:我想我应该提到我无法控制 JSON,而且我知道通常我的 C# 对象应该与 JSON 匹配。我的问题不是“为什么不反序列化?”。我知道为什么不是。我在问是否有办法按照我要求的方式反序列化 JSON。
我正在使用 Newtonsoft.Json。
我有一个包含 1 个对象的 JSON 字符串。我需要将该对象反序列化为带有嵌套对象的 C# 对象。
所以可以说我的 JSON 看起来像这样。
{
"id": 123,
"userName": "fflintstone",
"address": "345 Cave Stone Road",
"address2": "",
"city": "Bedrock",
"state": "AZ",
"zip": "",
}
这是我的 C# 对象
public class Customer
{
public long Id { get; set; }
public string UserName { get; set; }
public AddressModel Address { get; set; }
}
AddressModel 地址属性是一个嵌套对象。该对象包含实际的地址属性。所以我需要反序列化我的 JSON 对象,以便将 id 和 userName 添加到 Customer 对象,然后将地址字段添加到嵌套的 Address 对象中。
我一直无法找到一种内置于 newtonsoft 的方法来完成此任务。有任何想法吗?
解决方案
您可以使用自定义 JsonConverter 来执行此操作。
public class CustomerJsonConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value is Customer customer)
{
var token = new JObject
{
["id"] = customer.Id,
["userName"] = customer.UserName,
["address"] = customer.Address.Address,
["address2"] = customer.Address.Address2,
["city"] = customer.Address.City,
["state"] = customer.Address.State,
["zip"] = customer.Address.ZIP
};
token.WriteTo(writer);
}
else
{
throw new InvalidOperationException();
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var obj = JToken.ReadFrom(reader);
if (obj.Type != JTokenType.Object)
{
return null;
}
return new Customer
{
Id = (long) obj["id"],
UserName = (string) obj["userName"],
Address = obj.ToObject<AddressModel>()
};
}
public override bool CanRead => true;
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Customer);
}
}
连同一个JsonConverterAttribute
上班Customer
。
[JsonConverter(typeof(CustomerJsonConverter))]
public class Customer
{
public long Id { get; set; }
public string UserName { get; set; }
public AddressModel Address { get; set; }
}
public class AddressModel
{
public string Address { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZIP { get; set; }
}
并这样利用:
var customer = JsonConvert.DeserializeObject<Customer>(customerJson);
或者,您可以简单地拥有一个中间映射模型。
public class CustomerFlattened
{
public long Id { get; set; }
public string UserName { get; set; }
public string Address { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZIP { get; set; }
public Customer ToCustomer()
{
return new Customer
{
Id = Id,
UserName = UserName,
Address = new AddressModel
{
Address = Address,
Address2 = Address2,
City = City,
State = State,
ZIP = ZIP
}
};
}
public static CustomerFlattened FromCustomer(Customer customer)
{
return new CustomerFlattened
{
Id = customer.Id,
UserName = customer.UserName,
Address = customer.Address.Address,
Address2 = customer.Address.Address2,
City = customer.Address.City,
State = customer.Address.State,
ZIP = customer.Address.ZIP
};
}
}
并这样利用:
var customer =
JsonConvert.Deserialize<CustomerFlattened>(
jsonOriginal
)
.ToCustomer();
var customerFlattened = CustomerFlattened.FromCustomer(customer);
var jsonConverted = JsonConvert.Serialize(customerFlattened );
推荐阅读
- xslt - XSLT 中不同 Xpath 之间的分组
- java - 如何将巨大的 id 列表(例如)传递给 apache spark 自定义数据源
- javascript - 使用 webpack 4.41 和 workbox 6 生成 ServiceWorker
- reactjs - React-Intl 同时使用多个语言环境
- flutter - StreamBuilder 快照 ConnectionState.done 不起作用
- python - 导航栏中的 Django 动态菜单
- javascript - PayPal 智能按钮交易显示错误
- javascript - 创建一个导入和修补另一个的 javascript 模块
- go - 如何使用光纤将密码解析为字节数组
- ruby-on-rails - html_safe 和非 html_safe 连接