2015-07-27 12 views
10

Ich verwende Json.NET zum Serialisieren/Deserialisieren einiger JSON-APIs.C# Enum-Deserialisierung mit Json.Net: Fehler beim Umwandeln des Werts in den Typ

Die API-Antwort enthält einige ganzzahlige Werte, die einer in der Anwendung definierten Enum zugeordnet werden.

public enum MyEnum 
    { 
     Type1, 
     Type2, 
     Type3 
} 

und die json API-Antwort hat die folgende:

ENUM wie dies

{ 
     "Name": "abc", 
     "MyEnumValue":"Type1" 
} 

manchmal die API einen Wert für die MyEnumValue Feld zurückgibt, die nicht in meine Enum definiert ist, wie folgt aus:

{ 
      "Name": "abc", 
      "MyEnumValue":"Type4" 
    } 

, die eine Ausnahme auslöst:

Fehler beim Konvertieren Wert „Type4“ eingeben ‚MyEnum‘

Gibt es eine Möglichkeit, diesen Fehler zu umgehen, indem ein Standardwert oder etwas Zuweisen der Absturz der Anwendung zu vermeiden?

+0

Haben Sie versucht, die 'DefaultValue' für die Eigenschaft Angabe http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_DefaultValueHandling.htm – 3dd

+0

Danke, ich versucht, aber immer noch die Ausnahme –

Antwort

6

Lassen Sie uns sagen, dass wir die folgende JSON-String haben:

[ 
    { 
     "Name": "abc", 
     "MyEnumValue": "Type1" 
    }, 
    { 
     "Name": "abcd", 
     "MyEnumValue": "Type2" 
    }, 
    { 
     "Name": "abcde", 
     "MyEnumValue": "Type3" 
    } , 
    { 
     "Name": "abcdef", 
     "MyEnumValue": "Type4" 
    } 
] 

und die folgende Klasse und Enum:

public class MyClass 
{ 
    public string Name { get; set; } 

    public MyEnum MyEnumValue { get; set; } 
} 

public enum MyEnum 
{ 
    Type1, 
    Type2, 
    Type3 
} 

Wie zu erkennen ist, die JSON-String-Array enthält Element (die letzte), die nicht korrekt auf die MyEnum abgebildet werden kann. Um zu vermeiden, Deserialisierung Fehler können Sie den folgenden Codeausschnitt verwenden:

static void Main(string[] args) 
{   
    var serializationSettings = new JsonSerializerSettings 
    { 
     Error = HandleDeserializationError 
    }; 

    var lst = JsonConvert.DeserializeObject<List<MyClass>>(jsonStr, serializationSettings); 
} 

public static void HandleDeserializationError(object sender, ErrorEventArgs errorArgs) 
{ 
    errorArgs.ErrorContext.Handled = true; 
    var currentObj = errorArgs.CurrentObject as MyClass; 

    if (currentObj == null) return; 
    currentObj.MyEnumValue = MyEnum.Type2;    
} 

wo die jsonStr Variable über die geposteten JSON-String ist. Wenn MyEnumValue im obigen Codebeispiel nicht korrekt interpretiert werden kann, wird der Standardwert Type2 festgelegt.

Beispiel: https://dotnetfiddle.net/WKd2Lt

+0

geworfen Danke, das ist eine nette Lösung –

+0

Huch, wie ist das Zuweisen eines Defaultwertes eine Lösung? Vielleicht können Typ 5 oder Typ 6 oder Typ X nicht mit Typ 2 gleichgesetzt werden? Der Punkt ist, dass der Client nicht voraussehen kann, was der Server in Zukunft zurückgeben wird, vorausgesetzt, Sie können einen Standardwert zuweisen, der gefährlich ist. –

8

Die einzige Art, wie ich es sehe, sollten Sie Ihren eigenen Konverter schreiben. Aber die Hälfte der Arbeit ist bereits in Klasse StringEnumConverter erledigt. Wir können

class Program 
{ 
    static void Main(string[] args) 
    { 
     const string json = @"{ 
       'Name': 'abc', 
       'Type':'Type4' 
      }"; 

     // uncomment this if you want to use default value other then default enum first value 
     //var settings = new JsonSerializerSettings(); 
     //settings.Converters.Add(new FooTypeEnumConverter { DefaultValue = FooType.Type3 }); 

     //var x = JsonConvert.DeserializeObject<Foo>(json, settings); 

     var x = JsonConvert.DeserializeObject<Foo>(json); 
    } 
} 

public class Foo 
{ 
    public string Name { get; set; } 

    public FooType Type { get; set; } 
} 

public enum FooType 
{ 
    Type1, 
    Type2, 
    Type3 
} 

public class FooTypeEnumConverter : StringEnumConverter 
{ 
    public FooType DefaultValue { get; set; } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     try 
     { 
      return base.ReadJson(reader, objectType, existingValue, serializer); 
     } 
     catch (JsonSerializationException) 
     { 
      return DefaultValue; 
     } 
    } 
} 
+0

Danke, das kann eine andere alternative Lösung sein –

0

Eine Alternative nur ReadJson Methode überschreiben, wenn Sie keinen benutzerdefinierten Konverter erstellen möchten, ist es zu einem privaten String-Feld in Ihrem DTO abzubilden und dann Enum.TryParse verwenden in diesem Bereich Eigentum Getter:

public class MyClass 
{ 
    [JsonProperty("MyEnumValue")] 
    private string myEnumValue; 

    public string Name { get; set; } 

    [JsonIgnore] 
    public MyEnum MyEnumValue 
    { 
     get 
     { 
      MyEnum outputValue = MyEnum.Default; 
      Enum.TryParse(myEnumValue, out outputValue); 
      return outputValue; 
     } 
    } 
} 
Verwandte Themen