Newtonsoft.JSON kann das Modell nicht mit dem TypeConverter-Attribut konvertieren

8

Ich habe eine Anwendung C # MVC , die Daten als JSON-Zeichenfolgen in einem XML-Dokument und auch in MySQL DB-Tabellen speichert.

Vor kurzem erhielt ich die Anforderung, JSON-Strings in MySQL-Datenbankfeldern zu speichern , um über C # -Objekte über Newtonsoft.Json konvertiert zu werden. Daher habe ich beschlossen, einen TypeConverter zu implementieren um JSON-Zeichenfolgen in benutzerdefinierte C # -Modelle zu konvertieren.

Leider kann ich den folgenden Befehl nirgends in meiner Lösung verwenden, um meine JSON-Strings zu deserialisieren, wenn das Attribut TypeConverter zu meinem C # -Modell hinzugefügt wird :

%Vor%

Durch das Entfernen des Attributs wird das Problem behoben. Dies verhindert jedoch, dass MySQL-Datenbankfelder in benutzerdefinierte C # -Objekte konvertiert werden.

Hier ist mein C # -Modell mit dem TypeConverter-Attribut, das hinzugefügt wurde:

%Vor%

Hier ist meine TypeConverter-Klasse :

%Vor%

Sobald ich das Attribut der Foo-Klasse hinzufüge, erhalte ich den folgenden Fehler:

Das aktuelle JSON-Objekt (z. B. {"name": "value"}) kann nicht in den Typ 'Models.Foo' deserialisiert werden, da der Typ zur korrekten Deserialisierung einen JSON-Zeichenfolgenwert benötigt.

Um diesen Fehler zu beheben, ändern Sie den JSON entweder in einen JSON-Zeichenfolgenwert oder ändern Sie den deserialisierten Typ so, dass es ein normaler .NET-Typ ist (z. B. kein primitiver Typ wie ganze Zahlen, kein Sammlungstyp wie ein Array oder) Liste), die aus einem JSON-Objekt deserialisiert werden kann. JsonObjectAttribute kann auch zum Typ hinzugefügt werden, um die Deserialisierung von einem JSON-Objekt zu erzwingen.

Ich verwende die folgende Zeichenfolge (die perfekt funktioniert, ohne das TypeConverter-Attribut hinzuzufügen):

%Vor%

Nicht sicher, was hier vor sich geht, irgendwelche Ideen?

Vielen Dank !!!

AKTUALISIEREN

Ich habe festgestellt, dass ich auch Probleme mit MVC-API-Controllern habe, die die Testklasse mit Foo als Eigenschaft oder auf Controllern akzeptieren, die akzeptieren Foo als Objekt , wenn das TypeConverter-Attribut zur Foo-Klasse hinzugefügt wird.

Hier ist ein Beispiel für einen Testcontroller, der Probleme hat:

%Vor%

Der TypeConverter verursacht möglicherweise Probleme beim Überschreiben der Bindung des WebAPI-Modells und gibt null zurück, wenn eine der obigen Aktionen JSON über AJAX mit der folgenden Struktur empfängt:

%Vor%

Wenn das TypeConverter-Attribut zur Foo-Klasse hinzugefügt wird, wird die folgende Methode in der FooConverter TypeConverter-Klasse aufgerufen, sobald die Route gefunden wird:

%Vor%

Die ConvertFrom-Methode auf dem FooConverter TypeController wird NICHT von der Aktion des ApiControllers aufgerufen, die die Ursache des Problems sein kann.

Es ist wieder eine ähnliche Situation, in der die Controller-Aktionen ohne das TypeConverter-Attribut funktionieren.

Jede weitere Hilfe wird sehr geschätzt !!

Vielen Dank.

    
Steve 09.07.2015, 18:50
quelle

1 Antwort

13

Hier gibt es ein paar Dinge. Zunächst ein vorläufiges Problem: Auch wenn kein TypeConverter angewendet wurde, entspricht Ihr JSON nicht Ihrer Klasse Foo , sondern entspricht einer Containerklasse, die eine Foo -Eigenschaft enthält, zum Beispiel:

%Vor%

i.e. Bei Ihrer JSON-Zeichenfolge funktioniert Folgendes nicht:

%Vor%

Aber das Folgende wird:

%Vor%

Ich vermute, das ist einfach ein Fehler in der Frage, also nehme ich an, dass Sie eine Klasse deserialisieren möchten, die eine Eigenschaft Foo enthält.

Das Hauptproblem, das Sie sehen, ist, dass Json.NET versuchen wird, ein TypeConverter zu verwenden, wenn eines vorhanden ist, um eine zu serialisierende Klasse in eine JSON-Zeichenfolge zu konvertieren. In den Dokumenten :

  

Primitive Typen

     

.Net: TypeConverter (konvertierbar in String)
  JSON: Zeichenfolge

Aber in Ihrem JSON ist Foo keine JSON-Zeichenfolge, sondern ein JSON -Objekt . Daher tritt bei der Deserialisierung ein Fehler auf, sobald der Typkonverter angewendet wird. Ein eingebetteter String würde so aussehen:

%Vor%

Beachten Sie, wie alle Anführungszeichen gemerkt wurden. Und selbst wenn Sie Ihr JSON-Format für Foo -Objekte geändert haben, um damit übereinzustimmen, würde Ihre Deserialisierung immer noch fehlschlagen, da die TypeConverter und Json.NET versuchen, sich gegenseitig rekursiv aufzurufen.

Sie müssen also die Verwendung von TypeConverter von Json.NET global deaktivieren und auf die Standardserialisierung zurückgreifen, während Sie in allen anderen Situationen die TypeConverter beibehalten. Dies ist ein bisschen schwierig, da es kein Json.NET-Attribut gibt, das Sie anwenden können, um die Verwendung von zu deaktivieren type converters, stattdessen benötigen Sie einen speziellen Contract Resolver und ein spezielles JsonConverter , um davon Gebrauch zu machen:

%Vor%

Und benutze es wie:

%Vor%

Beispiel Geige .

Schließlich sollten Sie die Methode ConvertTo wahrscheinlich auch in Ihrem Typkonverter implementieren, siehe Vorgehensweise: Implementieren Sie einen Typkonverter .

    
dbc 09.07.2015, 21:00
quelle