2012-02-07 16 views
7

Potrzebuję serializować obiekty do JSON. Chciałbym to zrobić za pomocą szablonu zamiast adnotacji danych (tak jak robi większość frameworków). Czy ktoś wie, jak to zrobić?Serializowanie obiektów obiektów w języku C# do JSON

Zdjęcie przedstawia ponad 1000 słów. Szukam czegoś, co wygląda tak:

enter image description here

Na przykład, gdybym miał klasę tak:

public class Test 
{ 
    public string Key { get; set; } 
    public string Name { get; set; } 
    public string Code { get; set; } 
    public Test Related { get; set; } 
} 

iw miał szablon ciąg mógłby wyglądać tak :

{ 
    id: "$Key", 
    name: "$Name", 
    related: "$Related.Name" 
} 

Chcę uzyskać obiekt JSON, którego właściwości są wypełniane zgodnie z Key, Name i Related.Name obiektu.

Zasadniczo szukam dla JSON serializacji metody, która obsługuje templating zamiast.

+0

Nie jest jasne, czego dokładnie chcesz. Czy chcesz utworzyć metodę, która ma ten szablon zakodowany na sztywno i działa na każdym typie, który ma 'Klucz',' Nazwa' i 'Powiązane.Nazwa'? A może chcesz kompletny system, który może zrozumieć szablony w określonym formacie i serializować je za pomocą? – svick

+0

@ KeesC.Bakker Nikt nie jest zobowiązany do wyjaśnienia upadków, ponieważ zaniżanie jest anonimowe. Dodatkowo, to pytanie nie wykazuje żadnych wysiłków badawczych i jest niewiarygodnie niejasne (i można argumentować, że nie jest to również konstruktywne, ponieważ zasadniczo pytasz o listę produktów/przedmiotów). – casperOne

+1

@casperOne, nie zgadzam się, że to pytanie nie jest konstruktywne. Pyta, jak wykonać jedną konkretną rzecz. Myślę, że można to rozsądnie odpowiedzieć w sposób, który pasuje do SO, przynajmniej w obecnej formie. (Zredagowałem próbkę szablonu i próbowałem wyjaśnić to jeszcze bardziej.) – svick

Odpowiedz

4

nie wiem o wszelkich biblioteki, które wykonuje to dla ciebie, ale to nie jest takie trudne, żeby go zbudować samemu.

Jeśli posiadasz swój szablon, musisz przeanalizować go jako JSON, a następnie zastąpić wszystkie symbole zastępcze rzeczywistymi wartościami. Aby to zrobić, możesz użyć wzoru gościa.

Od JSON.NET (biblioteka JSON używam) nie wydają się mieć gościa, można utworzyć jeden siebie:

abstract class JsonVisitor 
{ 
    public virtual JToken Visit(JToken token) 
    { 
     var clone = token.DeepClone(); 
     return VisitInternal(clone); 
    } 

    protected virtual JToken VisitInternal(JToken token) 
    { 
     switch (token.Type) 
     { 
     case JTokenType.Object: 
      return VisitObject((JObject)token); 
     case JTokenType.Property: 
      return VisitProperty((JProperty)token); 
     case JTokenType.Array: 
      return VisitArray((JArray)token); 
     case JTokenType.String: 
     case JTokenType.Integer: 
     case JTokenType.Float: 
     case JTokenType.Date: 
     case JTokenType.Boolean: 
     case JTokenType.Null: 
      return VisitValue((JValue)token); 
     default: 
      throw new InvalidOperationException(); 
     } 
    } 

    protected virtual JToken VisitObject(JObject obj) 
    { 
     foreach (var property in obj.Properties()) 
      VisitInternal(property); 

     return obj; 
    } 

    protected virtual JToken VisitProperty(JProperty property) 
    { 
     VisitInternal(property.Value); 

     return property; 
    } 

    protected virtual JToken VisitArray(JArray array) 
    { 
     foreach (var item in array) 
      VisitInternal(item); 

     return array; 
    } 

    protected virtual JToken VisitValue(JValue value) 
    { 
     return value; 
    } 
} 

a następnie utworzenie wyspecjalizowanego gościa, który zastępuje symbole zastępcze rzeczywiste wartości:

class JsonTemplateVisitor : JsonVisitor 
{ 
    private readonly object m_data; 

    private JsonTemplateVisitor(object data) 
    { 
     m_data = data; 
    } 

    public static JToken Serialize(object data, string templateString) 
    { 
     return Serialize(
      data, (JToken)JsonConvert.DeserializeObject(templateString)); 
    } 

    public static JToken Serialize(object data, JToken template) 
    { 
     var visitor = new JsonTemplateVisitor(data); 

     return visitor.Visit(template); 
    } 

    protected override JToken VisitValue(JValue value) 
    { 
     if (value.Type == JTokenType.String) 
     { 
      var s = (string)value.Value; 

      if (s.StartsWith("$")) 
      { 
       string path = s.Substring(1); 

       var newValue = GetValue(m_data, path); 

       var newValueToken = new JValue(newValue); 

       value.Replace(newValueToken); 

       return newValueToken; 
      } 
     } 

     return value; 
    } 

    private static object GetValue(object data, string path) 
    { 
     var parts = path.Split('.'); 

     foreach (var part in parts) 
     { 
      if (data == null) 
       break; 

      data = data.GetType() 
       .GetProperty(part) 
       .GetValue(data, null); 
     } 

     return data; 
    } 
} 

Użycie jest wtedy proste.Na przykład za pomocą następującego wzoru:

{ 
    id : "$Key", 
    name: "$Name", 
    additionalInfo: 
    { 
     related: [ "$Related.Name" ] 
    } 
} 

Można użyć kodu jak poniżej:

JsonTemplateVisitor.Serialize(data, templateString) 

Wynik wówczas wygląda następująco:

{ 
    "id": "someKey", 
    "name": "Isaac", 
    "additionalInfo": { 
    "related": [ 
     "Arthur" 
    ] 
    } 
} 

Możesz też dodać jakiś błąd sprawdzanie, ale poza tym kod powinien zadziałać. Ponadto używa refleksji, więc może nie być odpowiedni, jeśli wydajność jest ważna.

+0

Spróbuję tego jutro. Wygląda obiecująco! Dzięki za wysiłek. –

0

Nie jestem pewien, co masz na myśli przez szablon, jeśli szukasz ogólnego serializatora json. Możesz znaleźć jeden z najszybszych serializerów Json dla .NET pod http://servicestack.net/.

Aby zainstalować ten pakiet z konsoli menedżera pakietów, można wykonać następujące polecenie.

 PM> Install-Package ServiceStack.Text 
+0

To wydaje się nie odpowiadać na pytanie. Nie chodzi tylko o serializator JSON. – svick

+0

Svick ma rację, szukam zarówno serializera, jak i sposobu na to, jakie właściwości chcę serializować. –

+1

@ KeesC.Bakker Nie rozumiem, dlaczego dostałem awans? Myślałem, że wyjaśniłem w mojej odpowiedzi, że nie rozumiem, o co ci chodzi w szablonach, a moja odpowiedź dotyczyła wyłącznie serializacji json. Teraz z obrazem dokładnie wiem, co chcesz osiągnąć. – ASetty

0

ServiceStack wydaje się być dobrym wyborem. enter image description here

http://www.servicestack.net/benchmarks/

+1

To wydaje się nie odpowiadać na pytanie. Nie chodzi tylko o serializator JSON. – svick

+0

Svick ma rację, szukam zarówno serializera, jak i sposobu na to, jakie właściwości chcę serializować. –

+1

@ Sick, przejdź do czego? Kiedy dodałem swoją odpowiedź, @ Kees C. Bakker nie przesłał jeszcze swojego 1000-tysięcznego obrazu. – ValidfroM

Powiązane problemy