C# 如果字符串值包装在同名对象中,如何干净地反序列化JSON
我想将一些奇怪的JSON反序列化到C#类: 为JSON生成以下类:C# 如果字符串值包装在同名对象中,如何干净地反序列化JSON,c#,json,json.net,deserialization,C#,Json,Json.net,Deserialization,我想将一些奇怪的JSON反序列化到C#类: 为JSON生成以下类: public class Name { public string Name { get; set; } } public class Product { public Name Name { get; set; } } public class ProductList { public List<Product> Product { get; set; } } public class
public class Name
{
public string Name { get; set; }
}
public class Product
{
public Name Name { get; set; }
}
public class ProductList
{
public List<Product> Product { get; set; }
}
public class Name2
{
public string Name { get; set; }
}
public class AddressLine1
{
public string AddressLine1 { get; set; }
}
public class Client
{
public ProductList ProductList { get; set; }
public Name2 Name { get; set; }
public AddressLine1 AddressLine1 { get; set; }
}
public class Result
{
public Client Client { get; set; }
}
public class RootObject
{
public Result Result { get; set; }
}
公共类名
{
公共字符串名称{get;set;}
}
公共类产品
{
公共名称名称{get;set;}
}
公共类产品列表
{
公共列表产品{get;set;}
}
公共类名称2
{
公共字符串名称{get;set;}
}
公共类地址行1
{
公共字符串AddressLine1{get;set;}
}
公共类客户端
{
公共产品列表产品列表{get;set;}
公共名称2名称{get;set;}
公共地址行1地址行1{get;set;}
}
公开课成绩
{
公共客户端{get;set;}
}
公共类根对象
{
公共结果结果{get;set;}
}
问题是对象中重复的属性名称(Product
中的Name
和Client
,Client
中的AddressLine1
)迫使我创建一个只有一个字符串属性(Name
,AddressLine1
)的额外类,以便能够反序列化JSON
生成的代码也是无效的,因为成员名称不能与其封闭类型相同(但我知道可以使用[JsonProperty(PropertyName=“Name”)]
属性来解决这个问题)
要避免类层次结构中不必要的级别,并拥有一个干净的类结构,以便能够使用JSON.NET反序列化此JSON,最好的方法是什么?请注意,这是一个第三方API,因此我不能只更改JSON。听起来您可能对实现自定义的
JsonConverter
感兴趣。这有一些你如何做到这一点的例子。这是一个相当简单的过程,可以让您在拥有自己最熟悉的类结构的同时保留所使用的JSON。事实上,对于API结果来说,这是一种奇怪的格式,使其更难使用。解决这个问题的一个方法是创建一个定制的JsonConverter
,它可以接受一个包装值并返回内部值,就像包装器不在那里一样。这将允许您将笨拙的JSON反序列化为更合理的类层次结构
下面是一个应该可以工作的转换器:
class WrappedObjectConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return true;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
// Get the value of the first property of the inner object
// and deserialize it to the requisite object type
return token.Children<JProperty>().First().Value.ToObject(objectType);
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
(请注意,如果结果
对象将不包含除客户端
之外的任何其他属性,则可以在那里应用WrappedObjectConverter
,并将客户端
向上移动到根对象
并消除结果
类。)
下面是一个演示,演示了转换器的工作情况:
class Program
{
static void Main(string[] args)
{
string json = @"
{
""Result"": {
""Client"": {
""ProductList"": {
""Product"": [
{
""Name"": {
""Name"": ""Car polish""
}
}
]
},
""Name"": {
""Name"": ""Mr. Clouseau""
},
""AddressLine1"": {
""AddressLine1"": ""Hightstreet 13""
}
}
}
}";
RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);
Client client = obj.Result.Client;
foreach (Product product in client.ProductList)
{
Console.WriteLine(product.Name);
}
Console.WriteLine(client.Name);
Console.WriteLine(client.AddressLine1);
}
}
删除其中一个名称或名称2。不能更改json生成过程吗?如果输出更干净,这可能是一个更好的解决方案!不,我不能更改JSON。这是从一个公共休息室收到的。这对我来说是一个很好的开始,谢谢!我的嵌套属性并不是唯一的,这增加了复杂性。所以我有解析所有字段的方法,但要特别对待这一字段。这里有一个例子:“地址”:{“@attributes”:{“地址类型”:“prop”},“地址”:“12街”,“城市”:“B”,“州”:“MD”,“邮政编码”:“12”,“国家”:“美国”、“电子邮件”:fu@fu.co}为什么我们需要重复“Name”和“AddressLine1”。我们不能让反序列化程序使用更简单的字符串,例如:{“Result”:{“Client”:{“ProductList”:[{“Name”:“Car polish”}],“Name”:“Clouseau先生”,”AddressLine1:“Hightstreet 13”}}@当然是progLearner;理想的解决方案是使JSON更简单、更易于使用。问题是JSON通常由第三方API控制,因此作为消费者,您必须按原样处理它,除非您能够说服API提供商对其进行更改。这个答案的重点是展示如何处理有缺陷的JSON if你不能更改。非常感谢,我创建了以下帖子:
public class RootObject
{
public Result Result { get; set; }
}
public class Result
{
public Client Client { get; set; }
}
public class Client
{
[JsonConverter(typeof(WrappedObjectConverter))]
public List<Product> ProductList { get; set; }
[JsonConverter(typeof(WrappedObjectConverter))]
public string Name { get; set; }
[JsonConverter(typeof(WrappedObjectConverter))]
public string AddressLine1 { get; set; }
}
public class Product
{
[JsonConverter(typeof(WrappedObjectConverter))]
public string Name { get; set; }
}
class Program
{
static void Main(string[] args)
{
string json = @"
{
""Result"": {
""Client"": {
""ProductList"": {
""Product"": [
{
""Name"": {
""Name"": ""Car polish""
}
}
]
},
""Name"": {
""Name"": ""Mr. Clouseau""
},
""AddressLine1"": {
""AddressLine1"": ""Hightstreet 13""
}
}
}
}";
RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);
Client client = obj.Result.Client;
foreach (Product product in client.ProductList)
{
Console.WriteLine(product.Name);
}
Console.WriteLine(client.Name);
Console.WriteLine(client.AddressLine1);
}
}
Car polish
Mr. Clouseau
Hightstreet 13