Der beste Weg, um mit dieser Situation umzugehen, ist die Verwendung eines benutzerdefinierten JsonConverter
.
Bevor wir zum Konverter gelangen, müssen wir eine Klasse definieren, in die die Daten deserialisiert werden sollen. Categories
Definieren Sie die Eigenschaft, die zwischen einem einzelnen Element und einem Array variieren kann, als List<string>
und markieren Sie sie mit einem [JsonConverter]
Attribut, damit JSON.Net den benutzerdefinierten Konverter für diese Eigenschaft verwenden kann. Ich würde auch empfehlen, [JsonProperty]
Attribute zu verwenden, damit den Elementeigenschaften unabhängig von der Definition in JSON aussagekräftige Namen zugewiesen werden können.
class Item
{
[JsonProperty("email")]
public string Email { get; set; }
[JsonProperty("timestamp")]
public int Timestamp { get; set; }
[JsonProperty("event")]
public string Event { get; set; }
[JsonProperty("category")]
[JsonConverter(typeof(SingleOrArrayConverter<string>))]
public List<string> Categories { get; set; }
}
Hier ist, wie ich den Konverter implementieren würde. Beachten Sie, dass ich den Konverter generisch gemacht habe, damit er bei Bedarf mit Zeichenfolgen oder anderen Objekttypen verwendet werden kann.
class SingleOrArrayConverter<T> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(List<T>));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Array)
{
return token.ToObject<List<T>>();
}
return new List<T> { token.ToObject<T>() };
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Hier ist ein kurzes Programm, das den Konverter in Aktion mit Ihren Beispieldaten demonstriert:
class Program
{
static void Main(string[] args)
{
string json = @"
[
{
""email"": ""john.doe@sendgrid.com"",
""timestamp"": 1337966815,
""category"": [
""newuser"",
""transactional""
],
""event"": ""open""
},
{
""email"": ""jane.doe@sendgrid.com"",
""timestamp"": 1337966815,
""category"": ""olduser"",
""event"": ""open""
}
]";
List<Item> list = JsonConvert.DeserializeObject<List<Item>>(json);
foreach (Item obj in list)
{
Console.WriteLine("email: " + obj.Email);
Console.WriteLine("timestamp: " + obj.Timestamp);
Console.WriteLine("event: " + obj.Event);
Console.WriteLine("categories: " + string.Join(", ", obj.Categories));
Console.WriteLine();
}
}
}
Und schließlich ist hier die Ausgabe der oben genannten:
email: john.doe@sendgrid.com
timestamp: 1337966815
event: open
categories: newuser, transactional
email: jane.doe@sendgrid.com
timestamp: 1337966815
event: open
categories: olduser
Geige: https://dotnetfiddle.net/lERrmu
BEARBEITEN
Wenn Sie in die andere Richtung gehen müssen, dh serialisieren, während Sie das gleiche Format beibehalten, können Sie die WriteJson()
unten gezeigte Methode des Konverters implementieren . (Stellen Sie sicher, dass Sie die CanWrite
Überschreibung entfernen oder in "Zurückgeben" ändern, da sie true
sonst WriteJson()
niemals aufgerufen wird.)
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
List<T> list = (List<T>)value;
if (list.Count == 1)
{
value = list[0];
}
serializer.Serialize(writer, value);
}
Geige: https://dotnetfiddle.net/XG3eRy