2012-05-25 16 views
9

Mam json jak tenPobierz Raw json ciąg w Newtonsoft.Json Biblioteki

{ 
    "name": "somenameofevent", 
    "type": "event", 
    "data": { 
     "object": { 
      "age": "18", 
      "petName": "18" 
     }, 
     "desct": { 
     } 
    } 
} 

i mam 2 obiekty jak ten

public class CustEvent 
{ 
    [JsonProperty("name")] 
    public string Name { get; set; } 
    [JsonProperty("type")] 
    public string EventType{ get; set; } 
    [JsonProperty("data")] 
    public SomeData Data{ get; set; } 
} 

public class SomeData 
{ 
    [JsonProperty("object")] 
    public String SomeObject { get; set;} 
    [JsonProperty("dsct")] 
    public String SomeDesct { get; set; } 
} 

używać do analizowania JSON do sprzeciwu Newtonsoft.NET bibliotekę. I jak mogę uzyskać RAW JSON w SomeObject, SomeDesct properties? W JSON "data.object ..." są obiektami złożonymi i chcę uzyskać tylko ciąg RAW JSON dla tych właściwości. Możesz mi pomóc ?

Odpowiedz

4

Musisz napisać niestandardową klasę konwertera (pochodzącą z Newtonsoft.Json.JsonConverter), która nakazuje deserializatorowi odczytanie całego obiektu i zwrócenie łańcucha JSON dla obiektu.

Następnie należy udekorować nieruchomość atrybutem JsonConverter.

[JsonConverter(typeof(YourCustomConverterClass))] 
public string SomeObject { get; set; } 

Istnieją dobre tutoriale w sieci na temat tworzenia niestandardowych konwerterów, ale - dla wygody - rdzeń konwertera może wyglądać następująco:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
{ 
    return JObject.Load(reader).ToString(); 
} 

Ta metoda odczytuje kompletnym JSON obiekt, ale zwraca serializowaną wersję obiektu jako ciąg znaków. Jest trochę narzut, ponieważ obiekt jest deserializowany do JObject, a następnie ponownie szeregowany, ale dla mnie jest to najłatwiejszy sposób na zrobienie tego. Może masz lepszy pomysł.

2

Jeśli martwisz się o koszty, ponieważ obiekt jest rozszeregować do JObject A, a następnie ponownie w odcinkach (rozwiązaniem oferowanym przez @fero) to można spróbować wykonać następujące czynności.

Approach 1: Stwórz swój własny JsonConverter i zastąpić ReadJson

using(var jsonReader = new JsonTextReader(myTextReader)) 
{ 
    while(jsonReader.Read()){ 
    if(jsonReader.TokenType.PropertyName=="SomeDesct") 
    { 
     //do what you want 
    } 
    } 
} 

Więcej szczegółów sprawdzić link Incremental JSON Parsing in C#

Podejście 2: Czytaj ciąg json i zastosować funkcje ciąg lub regex funkcja, aby uzyskać żądany ciąg znaków.

0

W twoim przypadku można bezpośrednio użyć metody statyczne z klasy JsonConvert

PopulateObject (wartość ciągu, docelowe obiekt, JsonSerializerSettings ustawienia);

0

Używam tej implementacji niestandardowego JsonConvertera.

public class RawJsonConverter: JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return objectType == typeof(string); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     var sb = new StringBuilder(); 
     JsonToken previousToken = JsonToken.None; 

     if (reader.TokenType == JsonToken.StartObject) 
     { 
      sb.Append('{'); 
      int depth = 1; 
      while (depth > 0) 
      { 
       if (!reader.Read()) 
        break; 
       switch (reader.TokenType) 
       { 
        case JsonToken.PropertyName: 
         if (previousToken == JsonToken.Boolean || previousToken == JsonToken.Integer || previousToken == JsonToken.Float) 
          sb.Append(','); 
         sb.AppendFormat("\"{0}\":", reader.Value); 
         break; 
        case JsonToken.StartArray: 
         if (previousToken == JsonToken.EndArray) 
          sb.Append(','); 
         sb.Append('['); 
         break; 
        case JsonToken.Boolean: 
        case JsonToken.Integer: 
        case JsonToken.Float: 
         if (previousToken == JsonToken.Boolean || previousToken == JsonToken.Integer || previousToken == JsonToken.Float) 
          sb.Append(','); 
         sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "{0}", reader.Value); 
         break; 
        case JsonToken.EndArray: 
         sb.Append(']'); 
         break; 
        case JsonToken.StartObject: 
         sb.Append('{'); 
         depth++; 
         break; 
        case JsonToken.EndObject: 
         sb.Append('}'); 
         depth--; 
         break; 
       } 
       previousToken = reader.TokenType; 
      } 
     } 
     return sb.ToString(); 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     writer.WriteRawValue(value.ToString()); 
    } 

    public override bool CanWrite 
    { 
     get 
     { 
      return true; 
     } 
    } 
} 
11

Nie trzeba pisać żadnych konwerterów, prostu użyć typu JRaw następująco:

public class SomeData 
{ 
    [JsonProperty("object")] 
    public JRaw SomeObject { get; set;} 
    [JsonProperty("dsct")] 
    public JRaw SomeDesct { get; set; } 
} 

Następnie można uzyskać dostęp do wartości surowca poprzez sprawdzenie właściwości .Value:

var rawJsonDesct = (string)data.SomeDesct.Value; 

Jeśli chcesz zachować podpis string, po prostu serializuj JSON do ukrytego pr operty i zamiast tego wywołać konwersję ciągów w wywołaniu akcesora.

+0

Zdecydowanie najprostsze rozwiązanie. – sroj

0

Jako chakrit suggested, możesz zrobić coś takiego, aby dostarczyć sygnaturę dla swojego obiektu, podczas gdy JRaw wykonuje prawdziwą pracę.

[JsonProperty("Data")] 
    public JRaw Raw { get; set; } 

    [JsonIgnore] 
    public string Data 
    { 
     get => Raw?.Value as string; 
     set => Raw = new JRaw(value); 
    }