Wie man mit JSON.net sowohl ein einzelnes Objekt als auch ein Array für dieselbe Eigenschaft behandelt


1 Answers

Ich arbeitete seit Ewigkeiten daran und danke Brian für seine Antwort. Alles, was ich hinzufügen möchte, ist die vb.net Antwort !:

Public Class SingleValueArrayConverter(Of T)
sometimes-array-and-sometimes-object
    Inherits JsonConverter
    Public Overrides Sub WriteJson(writer As JsonWriter, value As Object, serializer As JsonSerializer)
        Throw New NotImplementedException()
    End Sub

    Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
        Dim retVal As Object = New [Object]()
        If reader.TokenType = JsonToken.StartObject Then
            Dim instance As T = DirectCast(serializer.Deserialize(reader, GetType(T)), T)
            retVal = New List(Of T)() From { _
                instance _
            }
        ElseIf reader.TokenType = JsonToken.StartArray Then
            retVal = serializer.Deserialize(reader, objectType)
        End If
        Return retVal
    End Function
    Public Overrides Function CanConvert(objectType As Type) As Boolean
        Return False
    End Function
End Class

dann in deiner Klasse:

 <JsonProperty(PropertyName:="JsonName)> _
 <JsonConverter(GetType(SingleValueArrayConverter(Of YourObject)))> _
    Public Property YourLocalName As List(Of YourObject)

Hoffe das spart dir etwas Zeit

Question

Ich versuche, meine SendGridPlus-Bibliothek zu beheben, um mit SendGrid-Ereignissen umzugehen, aber ich habe einige Probleme mit der inkonsistenten Behandlung von Kategorien in der API.

In der folgenden Beispielnutzlast aus der SendGrid-API-Referenz werden Sie feststellen, dass die category für jedes Element entweder eine einzelne Zeichenfolge oder ein Array von Zeichenfolgen sein kann.

[
  {
    "email": "john.doe@sendgrid.com",
    "timestamp": 1337966815,
    "category": [
      "newuser",
      "transactional"
    ],
    "event": "open"
  },
  {
    "email": "jane.doe@sendgrid.com",
    "timestamp": 1337966815,
    "category": "olduser",
    "event": "open"
  }
]

Es scheint, dass meine Optionen, JSON.NET so zu machen, die Zeichenfolge reparieren, bevor sie kommt, oder JSON.NET zu konfigurieren, um die falschen Daten zu akzeptieren. Ich würde lieber kein String-Parsing durchführen, wenn ich damit durchkommen könnte.

Gibt es eine andere Möglichkeit, die ich mit Json.Net umgehen kann?




Ich hatte ein sehr ähnliches Problem. Mein Json Request war mir völlig unbekannt. Ich wusste es nur.

Es wird eine objectId geben und einige anonym Schlüsselwertpaare UND-Arrays.

Ich habe es für ein EAV-Modell verwendet, das ich gemacht habe:

Meine JSON Anfrage:

{objectId ": 2," firstName ":" Hans "," email ": [" a@b.de "," a@c.de "]," name ":" Andre "," etwas ": [" 232 "," 123 "]}

Meine Klasse habe ich definiert:

[JsonConverter(typeof(AnonyObjectConverter))]
public class AnonymObject
{
    public AnonymObject()
    {
        fields = new Dictionary<string, string>();
        list = new List<string>();
    }

    public string objectid { get; set; }
    public Dictionary<string, string> fields { get; set; }
    public List<string> list { get; set; }
}

und jetzt, da ich unbekannte Attribute mit ihrem Wert und ihren Arrays deserialisieren möchte, sieht mein Converter so aus:

   public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        AnonymObject anonym = existingValue as AnonymObject ?? new AnonymObject();
        bool isList = false;
        StringBuilder listValues = new StringBuilder();

        while (reader.Read())
        {
            if (reader.TokenType == JsonToken.EndObject) continue;

            if (isList)
            {
                while (reader.TokenType != JsonToken.EndArray)
                {
                    listValues.Append(reader.Value.ToString() + ", ");

                    reader.Read();
                }
                anonym.list.Add(listValues.ToString());
                isList = false;

                continue;
            }

            var value = reader.Value.ToString();

            switch (value.ToLower())
            {
                case "objectid":
                    anonym.objectid = reader.ReadAsString();
                    break;
                default:
                    string val;

                    reader.Read();
                    if(reader.TokenType == JsonToken.StartArray)
                    {
                        isList = true;
                        val = "ValueDummyForEAV";
                    }
                    else
                    {
                        val = reader.Value.ToString();
                    }
                    try
                    {
                        anonym.fields.Add(value, val);
                    }
                    catch(ArgumentException e)
                    {
                        throw new ArgumentException("Multiple Attribute found");
                    }
                    break;
            }

        }

        return anonym;
    }

So, jetzt jedes Mal wenn ich ein AnonymObject bekomme, kann ich durch das Wörterbuch iterieren und jedes Mal, wenn es mein Flag "ValueDummyForEAV" gibt, wechsle ich zu der Liste, lese die erste Zeile und spalte die Werte. Danach lösche ich den ersten Eintrag aus der Liste und fahre fort mit Iteration aus dem Dictionary.

Vielleicht hat jemand das selbe Problem und kann das nutzen :)

Grüße Andre






Related