@Alan Buchanan shows eine schöne einfache Art und Weise zu erreichen, was Sie in Ihrer Frage beschrieben. Wenn Sie Ihrer Klasse jedoch keine weiteren Eigenschaften hinzufügen möchten, müssen Sie stattdessen eine benutzerdefinierte JsonConverter
verwenden. Hier ist ein Beispiel dafür, wie Sie es schreiben können:
class PersonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Person);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
Person person = (Person)value;
JObject result = new JObject();
result.Add("id", person.Id);
result.Add("fullname", (person.FirstName + " " + person.LastName).Trim());
result.Add("address", (person.Address1 + " " + person.Address2).Trim());
result.WriteTo(writer);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject obj = JObject.Load(reader);
Person person = new Person();
person.Id = (int)obj["id"]; // assuming id will always be present in the JSON
string fullName = (string)obj["fullname"];
if (fullName != null)
{
string[] parts = fullName.Split(new char[] { ' ' }, 2);
// if there's only 1 part, I'm assuming it is the first name
if (parts.Length > 0)
person.FirstName = parts[0];
if (parts.Length > 1)
person.LastName = parts[1];
}
person.Address1 = (string)obj["address"]; // don't bother trying to split address
return person;
}
}
Sie werden bemerken, die PersonConverter
Klasse enthält drei Methoden, von denen alle erforderlichen durch die JsonConverter
abstrakte Basisklasse implementiert werden es erbt von: CanConvert
, ReadJson
und WriteJson
.
Die CanConvert
Methode teilt Json.Net mit, dass dieser Konverter Person
Objekte handhabt. Diese Methode kann von Json.Net abhängig von der Verwendung des Konverters aufgerufen werden oder nicht. Mehr dazu später.
WriteJson
ist verantwortlich für das Erstellen des JSON für das Zielobjekt während der Serialisierung. Sie können hier sehen, dass ich intern ein JObject
verwende, um das JSON unter Verwendung von Daten in der Klasse Person
aufzubauen. Sie können Methoden auch direkt auf dem Writer aufrufen, anstatt eine JObject
zu verwenden, aber ich finde es auf diese Weise etwas umständlicher.
ReadJson
behandelt das Gegenteil: Rekonstruieren des Objekts aus dem JSON während der Deserialisierung. Wieder verwende ich einen JObject
als Vermittler, um die Daten vom Leser zu erhalten, bevor es in die neue Person
Instanz aufgeteilt wird.
Wenn Sie nur serialisiert und nicht deserialisieren benötigen, können Sie CanRead
außer Kraft setzen false
zurückzukehren, und dann nur ReadJson
ein NotImplementedException
werfen machen. In ähnlicher Weise gibt es eine CanWrite
Eigenschaft, die Sie überschreiben können, wenn Sie nur die Serialisierung, aber keine Serialisierung durchführen müssen.
Es gibt zwei Möglichkeiten, eine verwenden JsonConverter
: Sie können entweder eine Instanz auf die serialize/deserialize Methoden (entweder über Methodenparameter oder JsonSerializerSettings
) passieren ...
string json = JsonConvert.SerializeObject(p, new PersonConverter());
... oder Sie verwenden können, ein [JsonConverter]
Attribut den Konverter an Ihre Klasse zu binden:
[JsonConverter(typeof(PersonConverter))]
public class Person
{
...
}
Wenn Sie die erste Methode verwenden, dann Json.Net ruft CanConvert
, um zu bestimmen, welche Art (en) Ihre Konverter verarbeiten kann. Wenn Sie das Attribut verwenden, wird CanConvert
nie aufgerufen, da Json.Net davon ausgeht, dass Sie den korrekten Konvertierungstyp im Attribut für die Zielklasse angegeben haben.
Hier ist ein Round-Trip-Demo: https://dotnetfiddle.net/EGok23
OP sagt klar, dass er bereits JSON.net verwendet. Keine Notwendigkeit für die zusätzlichen Anweisungen in Bezug auf Newtonsoft, sie sind die gleiche Sache –
Dank Alan, ich benutze Newtonsoft.Json (Ich lernte gestern die meisten Suchen kommen mit Json.Net, da es die gleiche Sache ist) =) Allerdings habe ich einige Bedenken, weil ich andere Felder habe, die ich serialisieren/deserialisieren muss, die einem ähnlichen Muster folgen und nicht möchten, dass es so eingerichtet wird. Ich werde meine Frage aktualisieren, um dies zu reflektieren. – RoLYroLLs
Tut mir leid, ich neige dazu, die Frage zu vereinfachen, also ist es nicht so groß/komplex, aber dann erkenne ich, wenn gegebene Antworten, dass * ich es kompliziert gemacht habe. Ihre Antwort lohnt sich jedoch für andere Szenarien, die ich habe. – RoLYroLLs