2017-11-17 1 views
0

I eine benutzerdefinierte JsonConverter zur Verwendung als solche implementieren möchten,C# JsonConverter JSONArray bespannen w/Abscheider und zurück

[JsonConverter(typeof(ArrayString))] 
    public string ServiceCodes { get; set; } 

Der Zweck ist es, eine JSON Array in einen String mit Separatoren zu konvertieren, zum Beispiel ["this", "is", "my", "json", "array"] sollte "this;is;my;json;array" (oder was auch immer Separator) werden. Ebenso sollte das Umgekehrte möglich sein.

Ich habe Mühe zu verstehen, die WriteJson Methode von JsonConverter überschreiben.

Um einen Kontext bereitzustellen, ist ServiceCodes eine Eigenschaft auf einer Entität (ich verwende EF6). Ich denke, es ist einfacher, das zu tun, was ich für meinen Fall erwarte, als andere Implementierungen. Eine Frage, die ich habe, ist jedoch wann ist der JsonConverter aufgerufen?

Ich möchte nur die get geben Json, wenn der Getter json wünscht, nämlich, wenn das Objekt, das diese Eigenschaft enthält, als JSON von meiner API zurückgegeben wird. Ich möchte nicht, dass dieser Konverter aufgerufen wird, wenn ich zum Beispiel LINQ schreibe.

Jede Hilfe wäre dankbar, danke.

EDIT - Info hinzugefügt

Hier ist die Klasse und einige moc Daten.

[ComplexType] 
    public class TerminalDuties 
    { 
     public string TerminalCode { get; set; } 

     public string TransportationCode { get; set; } 

     [JsonConverter(typeof(ArrayString))] 
     public string ServiceCodes { get; set; } 
    } 

"Origin": { "TerminalCode": "MIA", "TransportationCode": "GT", "ServiceCodes": ["WH", "HL"] }

Ich versuchte @ felix-b Antwort, aber es war nicht Mapping. Das Objekt war null. Ich hatte Haltepunkte in der ArrayString-Klasse, aber sie wurden nicht getroffen. Vermutlich hat es nicht versucht zuzuordnen, da die Eigenschaft eine Zeichenkette ist. Was ist die Problemumgehung?

Hier ist, wie es in meinem Web-API-Controller (erbt von ApiController)

[HttpPost] 
    public void DoStuff([FromBody]Thing t) 
    { 
     someMngr.Add(t); 
    } 

    public class Thing : ParentClass 
    { 
     properties... 
     public TerminalDuties Origin { get; set; } 
    } 
+0

Wenn Sie von '" diese zu konvertieren suchen, ist ; an; array "' zu '[" this "," is "," an "," array "]', müssen Sie einen benutzerdefinierten Konverter schreiben, um es zu tun (vielleicht nur eine einfache 'string.Split' .. ?). Das 'JsonConverter'-Attribut wird nur verwendet, wenn ein Json-Serializer zum Konvertieren des Objekts verwendet wird. Beginnen Sie damit, zu verstehen, welches Web-Framework Sie verwenden - ASP.NET MVC, ASP.NET Web API usw.? Und dann grenzen Sie Ihre Suche ein, wie Sie die Antwort von Ihren API-Methoden serialisieren. –

+0

Danke, @GeoffJames! Ich bin gerade in ASP.NET Web API 2. Ja, ich plane die Verwendung von string.Split und string.Join. Mein Kopf ist gerade voll und versucht es in den JsonConverter-Methoden. – brnis

+0

Keine Sorge. Ich würde es einen Schritt nach dem anderen machen. Ziehe ihn dorthin zurück, wo du angefangen hast (vor dem Attribut usw.), und erhalte zuerst JSON in den Anfragen. Wenn Sie sicher sind, dass das funktioniert, können Sie mit Ihrem benutzerdefinierten Konverter arbeiten. Sonst versucht man, viele Probleme auf einmal zu lösen, und kann nicht immer sicher sein, welche Ursache/Wirkung gerade geändert wurde usw. –

Antwort

2

Getestet mit .NET Framework 4.6.1, ASP.NET Web API 2, Entity Framework 6.1.3, Newtonsoft ausgesetzt ist. Json 10.0.3.

UPDATE

ursprünglich Meine Antwort [JsonConverter(typeof(ArrayString), ';')] angegeben, auf [JsonConverter(typeof(ArrayString))] in der Frage im Gegensatz zu werden benötigt.

Ich habe der Konverterklasse einen Standardkonstruktor hinzugefügt, so dass die Delimiterkonfiguration optional ist und Semikolon verwendet wird, wenn nicht angegeben. Jetzt funktioniert [JsonConverter(typeof(ArrayString))] entweder.

ORIGINAL ANTWORT

Der Konverter wird nur während der Serialisierung und Deserialisierung Ihrer Einheit durch JSON.NET aufgerufen werden. Es hat keinen Einfluss auf das Abrufen oder Festlegen von Eigenschaftswerten aus Code, weder auf LINQ-Abfragen noch auf DB-Operationen.

Hier Konverter Umsetzung:

public class ArrayString : JsonConverter 
{ 
    private readonly char _delimiter; 

    // UPDATE -- added default constructor, so that 
    // JsonConverter attribute can be specified without the 
    // delimiter parameter, in which case semicolon will be used 
    public ArrayString() : this(';') 
    { 
    } 

    public ArrayString(char delimiter) 
    { 
     _delimiter = delimiter; 
    } 

    public override bool CanRead => true; 
    public override bool CanWrite => true; 

    public override bool CanConvert(Type objectType) 
    { 
     return true; 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (reader.TokenType != JsonToken.StartArray) 
     { 
      return null; 
     } 

     var stringValue = new StringBuilder(); 

     while (reader.Read() && reader.TokenType == JsonToken.String) 
     { 
      if (stringValue.Length > 0) 
      { 
       stringValue.Append(_delimiter); 
      } 
      stringValue.Append((string)reader.Value); 
     } 

     return stringValue.ToString(); 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     var stringValue = value?.ToString(); 

     if (stringValue == null) 
     { 
      writer.WriteNull(); 
      return; 
     } 

     var arrayValue = stringValue.Split(_delimiter); 

     writer.WriteStartArray(); 

     foreach (var item in arrayValue) 
     { 
      writer.WriteValue(item); 
     } 

     writer.WriteEndArray(); 
    } 
} 

Hier ist, wie Sie ein Trennzeichen (Semikolon in diesem Beispiel) angeben:

[JsonConverter(typeof(ArrayString), ';')] 
public string ServiceCodes { get; set; } 
+0

Vielen Dank, @ felix-b! Ich habe gerade die Dokumentation auf www.newtonsoftjson.com durchgeblättert und mich am Kopf kratzt. Du bist der beste! – brnis

+0

* newtonsoft.com/json – brnis

+0

Beim POST-Vorgang wird der Eigenschaft kein JSON-Array zugeordnet. Ich denke, ich müsste einen benutzerdefinierten Mapper implementieren. Wäre das die richtige Richtung? – brnis