2016-09-25 11 views
1

JSON 요소를 구문 분석해야합니다. 때로는 단일 객체, 때로는 객체의 배열이 될 수 있습니다. 각 시나리오에 대해 별도의 클래스를 만드는 대신이 클래스를 단일 클래스로 원했습니다.두 개의 다른 JSON 형식을 deserialize 할 수 있도록 동일한 이름의 두 속성을 추가하는 방법은 무엇입니까?

public name name { get; set; } 
public name[] name { get; set; } 

스택 오버플로에서 비슷한 문제를 언급했습니다. 경우에 따라이를 해결하기 위해 인터페이스가 사용됩니다.

public class name : INames, INameLists 
{ 
    nameval INames.name { get; set; } 
    nameval[] INameLists.name { get; set; } 
} 

그러나 이것은 나를 위해 작동하지 않습니다. JSON 요소가 파싱되지 않고 예외가 발생합니다.

요소의 배열이 존재할 경우 배열로 구문 분석해야하며, 그렇지 않으면 단일 개체로 구문 분석해야한다는 조건이 필요합니다.

이 문제와 관련하여 도움을주십시오. 나는이 문제가 중복 될 것이라고 생각하지 않는다. 그렇다면 알려주세요.

+0

당신이 속성을 사용하려고합니까'[JsonProperty (PropertyName = "name")]' –

+0

JSON 자체가 통제에서 벗어 났습니까? 이것은 현재 JSON의 끔찍한 사용처럼 들립니다. JSON을 동적으로로드 (예 : Json.NET의 LINQ에서 JSON으로)하는 중간 단계를 거쳐 이름이 다른 것으로 수정 된 다음 일반 직렬 변환을 통해 피드 할 수 있습니다. –

+0

'public name name {get; 세트; } [JsonProperty (PropertyName = "name")] public name [] name1 {get; 세트; }' 이 코드를 사용해 보았습니다. 그러나 여전히 오류가 발생합니다. –

답변

2

사용자 정의 JavaScriptConverter 클래스를 사용하여 JSON 요소를 읽고 그로 인해 발생하는 문제를 해결할 수 있습니다. 즉, 이름이 배열 인 경우 클래스에 하나의 속성을 채우거나 단일 객체 인 경우, 다른 속성을 채 웁니다. 물론 질문에 표시된 것처럼 명시 적 인터페이스를 사용하지 않고 같은 이름의 두 멤버가있는 클래스를 정의 할 수 없으므로 속성의 이름이 달라야합니다.

이 같은 클래스 뭔가를 정의 할 수 있습니다 :

public class NameObject 
{ 
    public string[] Names { get; set; } 
    public string Name 
    { 
     get { return (Names != null && Names.Length > 0) ? Names[0] : null; } 
     set { Names = (value != null) ? new string[] { value } : null; } 
    } 
} 

당신은 Names 속성은 항상 실제 데이터를 보유하고 있음을 여기에서 볼 수 있습니다, 그리고 Name 속성은 하나의 이름이있는 경우에 단지 편리 . 여기

내가 변환기를 작성할 수 있습니다 방법입니다

public class NameObjectConverter : JavaScriptConverter 
{ 
    public override IEnumerable<Type> SupportedTypes 
    { 
     get { return new Type[] { typeof(NameObject) }; } 
    } 

    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) 
    { 
     NameObject nameObj = new NameObject(); 
     string singleName = GetValue<string>(dictionary, "name"); 
     if (singleName != null) 
     { 
      nameObj.Name = singleName; 
     } 
     else 
     { 
      ArrayList arrayList = GetValue<ArrayList>(dictionary, "name"); 
      nameObj.Names = (arrayList != null) ? arrayList.Cast<string>().ToArray() : null; 
     } 
     return nameObj; 
    } 

    private T GetValue<T>(IDictionary<string, object> dict, string key) 
    { 
     object value = null; 
     dict.TryGetValue(key, out value); 
     return value != null && typeof(T).IsAssignableFrom(value.GetType()) ? (T)value : default(T); 
    } 

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) 
    { 
     NameObject nameObj = (NameObject)obj; 
     Dictionary<string, object> dict = new Dictionary<string, object>(); 
     if (nameObj.Names != null && nameObj.Names.Length == 1) 
     { 
      dict.Add("name", nameObj.Name); 
     } 
     else 
     { 
      dict.Add("name", nameObj.Names); 
     } 
     return dict; 
    } 
} 

당신은에 등록해야하며, 컨버터를 사용하려면를 JavaScriptSerializer : 여기

var serializer = new JavaScriptSerializer(); 
serializer.RegisterConverters(new List<JavaScriptConverter> { new NameObjectConverter() }); 

행동의 컨버터를 보여주는 데모입니다 두 JSON 형식. (난 당신이 실제 JSON이 문제의 모양을 언급하지 않았기 때문에 여기에 일부 가짜 JSON을했습니다.)

public class Program 
{ 
    public static void Main(string[] args) 
    { 
     string json = @" 
     { 
      ""doctor"": { 
      ""name"": ""Dr. Herbert Q. Cunningham III"" 
      }, 
      ""patients"": { 
      ""name"": [ 
       ""Joe Schmoe"", 
       ""John Doe"", 
       ""Steve Smith"" 
      ] 
      } 
     }"; 

     var serializer = new JavaScriptSerializer(); 
     serializer.RegisterConverters(new List<JavaScriptConverter> { new NameObjectConverter() }); 
     MedicalData data = serializer.Deserialize<MedicalData>(json); 
     Console.WriteLine("Doctor's name: " + data.Doctor.Name); 
     Console.WriteLine("Patients' names: "); 
     foreach (string name in data.Patients.Names) 
     { 
      Console.WriteLine(" " + name); 
     } 
    } 
} 

public class MedicalData 
{ 
    public NameObject Doctor { get; set; } 
    public NameObject Patients { get; set; } 
} 

출력 :

Doctor's name: Dr. Herbert Q. Cunningham III 
Patients' names: 
    Joe Schmoe 
    John Doe 
    Steve Smith 
+0

아주 좋은 설명. 내 문제를 해결하는 데 도움이되었습니다. –

+0

기꺼이 도와 드리겠습니다. –