2012-07-03 11 views
5

ライブラリServiceStack.Textでオブジェクトをシリアル化しようとしています。これは私がServiceStack.TextでExpandoObjectをシリアライズ

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

しかし

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

を期待するように私は私が私の驚きに

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

なぜを取得し、取得

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

を作品!どうしたの?

第2に,私は何をしたいのですか?

+0

シリアライザがあなたのデータ構造を誤解しているようです...あなたは構造を投稿できますか? –

+0

ServiceStack.Textをインストールすると、上記のコードを実行できるはずです(usingステートメントを繰り返します)。 –

答えて

5

ExpandoObjectIConnection<KeyValuePair>IEnumerable<KeyValuePair>を実装しています:

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

私の推測では、内部で、ServiceStackシリアライザがIEnumerable<KeyValuePair>としてExpandoObjectを処理され、そしてそれは、キー/値ペアのJSON配列にシリアライズするということです。


これは.NETが実際にあなたのデータのための本当の(匿名)クラスを作成しますので、基本的にそれが可能あなたの最初の(作業)コードスニペットとは異なります自動的に

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

ので、シリアライザに送信されると、実際のプロパティを持つ実クラスで動作していますが、ExpandoObjectは実際にはobject[]の内部でサポートされています。


MicrosoftのSystem.Web.Helpers.Jsonも同じように動作します。このテストは合格:

[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); 
    } 

一つの最終編集:

あなたはDictionary<string, object>にあなたのExpandoObjectを回すことによって、この作品にあなたが望むように作ることができます。このコードの注意点は、データを辞書に複製するので、メモリに2つのコピーがある(または技術的に文字列がインターンされる可能性があるため少し下回る)ことです。

[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); 
    } 

、が、この後に渡って来て、実際にSystem.Web.Helpers.Jsonを使用している人のために、行うには良い事はちょうどラップされ、あなたのこのようなDynamicJsonObjectExpandoObject

[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); 
    } 

答私は働いた後、それを介して、私はここで同様の質問を見つけました:How to flatten an ExpandoObject returned via JsonResult in asp.net mvc?

+0

ありがとうございました。これは理にかなっています。任意のアイデアどのようにExpandoObjectを私が望むようにシリアル化できますか? –

+0

残念ながら、いいえ、私はしません。私は 'System.Web.Helpers.Json'をあなたの望むように動作させることを望んで試してみましたが、代わりにそれを提案するつもりでしたが、同じことをします。 :) – CodingWithSpike

+0

@MattHickford - 私の前のコメントを傷つける。私は私の答えの終わりに可能な解決策を追加しました。 – CodingWithSpike

関連する問題