2016-06-21 9 views
1

Ich habe einige JSON, die in zwei verschiedenen Formaten kommen kann. Manchmal ist der location Wert eine Zeichenfolge und manchmal ist es ein Objekt. Dies ist ein Beispiel des ersten Formats:JSON-Wert ist manchmal eine Zeichenfolge und manchmal ein Objekt

{ 
    "result": [ 
    { 
     "upon_approval": "Proceed to Next Task", 
     "location": "", 
     "expected_start": "" 
    } 
    ] 
} 

Klassendefinitionen für diese:

public class Result 
{ 
    public string upon_approval { get; set; } 
    public string location { get; set; } 
    public string expected_start { get; set; } 
} 

public class RootObject 
{ 
    public List<Result> result { get; set; } 
} 

Hier ist die JSON in dem zweiten Format:

{ 
    "result": [ 
    { 
     "upon_approval": "Proceed to Next Task", 
     "location": { 
     "display_value": "Corp-HQR", 
     "link": "https://satellite.service-now.com/api/now/table/cmn_location/4a2cf91b13f2de00322dd4a76144b090" 
     }, 
     "expected_start": "" 
    } 
    ] 
} 

Klassendefinitionen für diese:

public class Location 
{ 
    public string display_value { get; set; } 
    public string link { get; set; } 
} 

public class Result 
{ 
    public string upon_approval { get; set; } 
    public Location location { get; set; } 
    public string expected_start { get; set; } 
} 

public class RootObject 
{ 
    public List<Result> result { get; set; } 
} 

Wenn es Rializing, bekomme ich Fehler, wenn das JSON-Format nicht mit meinen Klassen übereinstimmt, aber ich weiß nicht im Voraus, welche Klassen verwendet werden, weil sich das JSON-Format ändert. Wie kann ich also diese beiden JSON-Formate dynamisch in einen Klassensatz deserialisieren?

Dies ist, wie ich jetzt Deserialisieren:

JavaScriptSerializer ser = new JavaScriptSerializer(); 
ser.MaxJsonLength = 2147483647; 
RootObject ro = ser.Deserialize<RootObject>(responseValue); 
+0

Kann Ihr "Ergebnis" -Array beide enthalten? – Eser

+0

@Eser Nein ich kann nur eine Klassendefinition von ihnen einschließen, aber JSON-Antwort hat entweder Zeichenfolge oder Klasse. Also weiß ich nicht, wie ich diese Zeichenfolgenwerte ignorieren kann. –

+1

[This] (http://stackoverflow.com/questions/22052430/how-to-handle-json-that-returns-both-a-string-and-a-string-array) kann Ihnen einen Hinweis geben .. .. – Eser

Antwort

2

Um dieses Problem zu lösen, werden Sie eine benutzerdefinierte JavaScriptConverter Klasse machen müssen und es mit dem Serializer registrieren. Der Serializer lädt die result Daten in eine Dictionary<string, object>, dann übergeben Sie den Konverter, wo Sie den Inhalt überprüfen und in ein verwendbares Objekt konvertieren können. Kurz gesagt, können Sie damit Ihre zweite Klasse von Klassen für beide JSON-Formate verwenden. Hier

ist der Code für den Konverter:

class ResultConverter : JavaScriptConverter 
{ 
    public override IEnumerable<Type> SupportedTypes 
    { 
     get { return new List<Type> { typeof(Result) }; } 
    } 

    public override object Deserialize(IDictionary<string, object> dict, Type type, JavaScriptSerializer serializer) 
    { 
     Result result = new Result(); 
     result.upon_approval = GetValue<string>(dict, "upon_approval"); 
     var locDict = GetValue<IDictionary<string, object>>(dict, "location"); 
     if (locDict != null) 
     { 
      Location loc = new Location(); 
      loc.display_value = GetValue<string>(locDict, "display_value"); 
      loc.link = GetValue<string>(locDict, "link"); 
      result.location = loc; 
     } 
     result.expected_start = GetValue<string>(dict, "expected_start"); 
     return result; 
    } 

    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) 
    { 
     throw new NotImplementedException(); 
    } 
} 

Dann ist es wie folgt verwenden:

var ser = new JavaScriptSerializer(); 
ser.MaxJsonLength = 2147483647; 
ser.RegisterConverters(new List<JavaScriptConverter> { new ResultConverter() }); 
RootObject ro = serializer.Deserialize<RootObject>(responseValue); 

Hier ist eine kurze Demo:

class Program 
{ 
    static void Main(string[] args) 
    { 
     string json = @" 
     { 
      ""result"": [ 
      { 
       ""upon_approval"": ""Proceed to Next Task"", 
       ""location"": { 
       ""display_value"": ""Corp-HQR"", 
       ""link"": ""https://satellite.service-now.com/api/now/table/cmn_location/4a2cf91b13f2de00322dd4a76144b090"" 
       }, 
       ""expected_start"": """" 
      } 
      ] 
     }"; 

     DeserializeAndDump(json); 
     Console.WriteLine(new string('-', 40)); 

     json = @" 
     { 
      ""result"": [ 
      { 
       ""upon_approval"": ""Proceed to Next Task"", 
       ""location"": """", 
       ""expected_start"": """" 
      } 
      ] 
     }"; 

     DeserializeAndDump(json); 

    } 

    private static void DeserializeAndDump(string json) 
    { 
     var serializer = new JavaScriptSerializer(); 
     serializer.RegisterConverters(new List<JavaScriptConverter> { new ResultConverter() }); 
     RootObject obj = serializer.Deserialize<RootObject>(json); 

     foreach (var result in obj.result) 
     { 
      Console.WriteLine("upon_approval: " + result.upon_approval); 
      if (result.location != null) 
      { 
       Console.WriteLine("location display_value: " + result.location.display_value); 
       Console.WriteLine("location link: " + result.location.link); 
      } 
      else 
       Console.WriteLine("(no location)"); 
     } 
    } 
} 

public class RootObject 
{ 
    public List<Result> result { get; set; } 
} 

public class Result 
{ 
    public string upon_approval { get; set; } 
    public Location location { get; set; } 
    public string expected_start { get; set; } 
} 

public class Location 
{ 
    public string display_value { get; set; } 
    public string link { get; set; } 
} 

Ausgang:

upon_approval: Proceed to Next Task 
location display_value: Corp-HQR 
location link: https://satellite.service-now.com/api/now/table/cmn_location/4a2cf91b13f2de00322dd4a76144b090 
---------------------------------------- 
upon_approval: Proceed to Next Task 
(no location) 
+0

Danke Brian, das war sehr hilfreich. Du hast meine Arbeit so einfach gemacht. Ich schulde dir jetzt so viel. –

+0

Keine Sorgen; Ich war froh, dass ich helfen konnte. –