이상한 JSON을 C # 클래스로 역 직렬화하고 싶습니다.
{
"Result": {
"Client": {
"ProductList": {
"Product": [
{
"Name": {
"Name": "Car polish"
}
}
]
},
"Name": {
"Name": "Mr. Clouseau"
},
"AddressLine1": {
"AddressLine1": "Hightstreet 13"
}
}
}
}
json2csharp 는 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 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; }
}
문제는 객체 ( Name
in Product
및 Client
, AddressLine1
in Client
) 의 중복 된 속성 이름으로 인해 JSON을 역 직렬화 할 수 있도록 하나의 문자열 속성 ( Name
, AddressLine1
) 만있는 추가 클래스를 생성 해야한다는 것입니다.
생성 된 코드도 유효하지 않습니다. 멤버 이름이 둘러싸는 유형과 같을 수 없기 때문입니다 (하지만 [JsonProperty(PropertyName = "Name")]
속성을 사용하여 해결할 수 있음을 알고 있습니다 ).
클래스 계층 구조에서 불필요한 수준을 피하고 JSON.NET을 사용하여이 JSON을 역 직렬화 할 수있는 깨끗한 클래스 구조를 갖는 가장 좋은 방법은 무엇입니까? 이것은 타사 API이므로 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();
}
}
이 변환기로 무장하면 추가 수준의 중첩을 제거하는 클래스 계층 구조를 만들 수 있습니다. [JsonConverter]
Json.Net이 사용자 지정 변환기를 적용 할시기를 알 수 있도록 속성 으로 "언 래핑"되어야하는 속성을 표시해야합니다 . 다음은 향상된 클래스 구조입니다.
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; }
}
( Result
객체에을 제외한 다른 속성이 포함되지 않은 경우 Client
를 적용 WrappedObjectConverter
하여를 Client
위로 이동 RootObject
하고 Result
클래스를 제거 할 수 있습니다.)
다음은 작동중인 변환기를 보여주는 데모입니다.
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
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다