2012-07-03 15 views
5

Nesneleri kitaplık ServiceStack.Text ile seri hale getirmeye çalışıyorum. Ben olsunServiceStack.Text ile ExpandoObject'i Serileştirme

using System.Dynamic; 
using ServiceStack.Text; 
var x = new {Value= 10, Product = "Apples"};     
Console.WriteLine(JsonSerializer.SerializeToString(x)); 

Bu benim

{"Value":10,"Product":"Apples"} 

beklediğiniz gibi çalışır Ancak

dynamic x = new ExpandoObject(); 
x.Value = 100; 
x.Product = "Apples"; 
Console.WriteLine(JsonSerializer.SerializeToString(x)); 

alıyorum benim için sürpriz

[{"Key":"Value","Value":100},{"Key":"Product","Value":"Apples"}] 

Neden! Neler oluyor?

İkincisi, nasıl İstediğimi alabilirim?

+0

Veri düzenleyiciniz veri yapınızı yanlış anlıyor gibi görünüyor ... yapıyı yayınlayabilir misiniz? –

+0

ServiceStack.Text'i yüklerseniz, yukarıdaki kodumu çalıştırabilmelisiniz (kullanım ifadelerini tekrarlayarak). –

cevap

5

ExpandoObjectIConnection<KeyValuePair> ve IEnumerable<KeyValuePair> uygular:

public sealed class ExpandoObject : 
    IDynamicMetaObjectProvider, 
    IDictionary<string, object>, 
    ICollection<KeyValuePair<string, object>>, 
    IEnumerable<KeyValuePair<string, object>>, 
    IEnumerable, INotifyPropertyChanged 

Bence olduğu dahili, ServiceStack seri hale getirici bir IEnumerable<KeyValuePair> olarak ExpandoObject muamele edilir ve bu nedenle anahtar/değer çiftleri JSON dizisine serializes. böylece ne zaman, sizin için otomatik

public class SomeNameTheCompilerMakesUp { 
    internal int Value { get; set; } 
    internal string Product { get; set; } 
} 

: .NET aslında veri için gerçek bir (anonim) sınıfı oluşturur çünkü


Bu temelde yapar, ilk (çalışma) kod parçacığı farklıdır serializer'a gönderilir, gerçek özellikleri ile gerçek bir sınıf ile çalışıyor, oysa ExpandoObject gerçekten dahili olarak bir object[] tarafından destekleniyor. Yan not


, Microsoft'un System.Web.Helpers.Json aynı şekilde davranır. Bu test geçer:

[TestMethod] 
    public void ExpandoObjectSerializesToJsonArray() 
    { 
     dynamic anonType = new { Value = 10, Product = "Apples" }; 

     dynamic expando = new ExpandoObject(); 
     expando.Value = 10; 
     expando.Product = "Apples"; 

     var anonResult = System.Web.Helpers.Json.Encode(anonType); 
     var expandoResult = System.Web.Helpers.Json.Encode(expando); 

     Assert.AreEqual("{\"Value\":10,\"Product\":\"Apples\"}", anonResult); 
     Assert.AreEqual("[{\"Key\":\"Value\",\"Value\":10},{\"Key\":\"Product\",\"Value\":\"Apples\"}]", expandoResult); 
    } 

Son bir düzenleme: Bir Dictionary<string, object> içine senin ExpandoObject çevirerek bu esere istediğiniz şekilde yapabilirsiniz

. Bu koddaki uyarı, verileri bir sözlükte çoğaltmasıdır. Bu nedenle, bellekte 2 kopyaya sahip olursunuz (ya da teknik olarak dizeler dahil edilebileceğinden biraz daha az).

[TestMethod] 
    public void TestMethod1() 
    { 
     dynamic expando = new ExpandoObject(); 
     expando.Value = 10; 
     expando.Product = "Apples"; 

     // copy expando properties to dictionary 
     var dictionary = ((ExpandoObject)expando).ToDictionary(x => x.Key, x => x.Value); 

     var expandoResult = System.Web.Helpers.Json.Encode(expando); 
     var dictionaryResult = System.Web.Helpers.Json.Encode(dictionary); 

     Assert.AreEqual("[{\"Key\":\"Value\",\"Value\":10},{\"Key\":\"Product\",\"Value\":\"Apples\"}]", expandoResult); 
     Assert.AreEqual("{\"Value\":10,\"Product\":\"Apples\"}", dictionaryResult); 
    } 

rağmen bu daha sonra rastlar ve aslında System.Web.Helpers.Json kullanan herkes için, yapacak daha iyi bir şey sadece sarın edilir senin böyle bir DynamicJsonObject içinde ExpandoObject:

[TestMethod] 
    public void TestMethod1() 
    { 
     dynamic expando = new ExpandoObject(); 
     expando.Value = 10; 
     expando.Product = "Apples"; 

     var dictionaryResult = System.Web.Helpers.Json.Encode(new DynamicJsonObject(expando)); 

     Assert.AreEqual("{\"Value\":10,\"Product\":\"Apples\"}", dictionaryResult); 
    } 

Ans çalıştığım zamanlar Bununla ilgili benzer bir soru buldum: How to flatten an ExpandoObject returned via JsonResult in asp.net mvc?

+0

Teşekkür Ralli, bu mantıklı. Herhangi bir fikir ExpandoObject'i istediğim şekilde nasıl seri hale getirebilir? –

+0

Maalesef, hayır, yapmam. System.Web.Helpers.Json'u istediğin şekilde çalışacağını ümit ettim ve alternatif olarak bunu teklif edeceğini ama aynı şeyi yapacağını umuyordum. :) – CodingWithSpike

+0

@MattHickford - önceki yorumumu kazımak. Cevabımın sonunda olası bir çözüm ekledim. – CodingWithSpike