C#の匿名型をJSON文字列にシリアル化するにはどうすればよいですか?


162

次のコードを使用して、匿名型をJSONにシリアル化しようとしています。

var serializer = new DataContractJsonSerializer(thing.GetType());
var ms = new MemoryStream();
serializer.WriteObject(ms, thing);
var json = Encoding.Default.GetString(ms.ToArray()); 

ただし、これを実行すると次の例外が発生します。

タイプ '<> f__AnonymousType1`3 [System.Int32、System.Int32、System.Object []]'はシリアル化できません。これをDataContractAttribute属性でマークし、シリアル化するすべてのメンバーをDataMemberAttribute属性でマークすることを検討してください。サポートされている他のタイプについては、Microsoft .NET Frameworkのドキュメントを参照してください。

(私の知る限り)匿名型に属性を適用することはできません。このシリアル化を行う別の方法はありますか、それとも何か不足していますか?

回答:


159

DataContractJsonSerializerの代わりにJavaScriptSerializerを試してください

JavaScriptSerializer serializer = new JavaScriptSerializer();
var output = serializer.Serialize(your_anon_object);

17
トラックバック、それはSP1で廃止されたようです。
ビスワナート

7
非常に不確かなものについては、MVCを含む多くの新しいMicrosoftフレームワークで使用されているようです。 aspnet.codeplex.com/SourceControl/changeset/view/21528#266491
Nick Berardi

1
このia non-asp.netプロジェクト(コンソールアプリケーション)を含めるにはどうすればよいですか?
Alxandr 2010

4
@Alxandr:ステートメントを参照System.Web.Extensions.dllして追加する必要がありusing System.Web.Script.Serialization;ます。
randomguy

1
@randomguiの問題は、プロジェクトの出力タイプがクライアントプロファイルに設定されていたことでした。
Alxandr 2010

75

他の人が述べたように、Newtonsoft JSON.NETは良いオプションです。次に、単純なJSONシリアル化の具体例を示します。

return JsonConvert.SerializeObject(
    new
    {
       DataElement1,
       SomethingElse
    });

私はそれが非常に柔軟で用途の広いライブラリであることを発見しました。


14

あなたは私のServiceStack試すことができJsonSerializerを、それはだ最速.NET JSONシリアライザの瞬間に。DataContract、任意のPOCOタイプ、インターフェース、匿名タイプを含む遅延バインディングオブジェクトなどのシリアル化をサポートします。

基本的な例

var customer = new Customer { Name="Joe Bloggs", Age=31 };
var json = customer.ToJson();
var fromJson = json.FromJson<Customer>(); 

注:他のJSON シリアライザーよりも最大で40倍から100倍遅いため、ベンチマークから除外する必要があったため、パフォーマンスが重要でない場合にのみ、MicrosoftのJavaScript シリアライザーを使用してください。


7
MVC3スタックでMS JavaScriptSerializerを使用して、少量のデータを持つオブジェクトをシリアル化しています。これらの場合はかなり高速で、ミリ秒未満で必要な処理を実行できます。DBクエリ自体の時間が50倍から100倍長くなるため、私の状況ではそれほど大きなボトルネックにはなりません。
ブライアン

2
時期尚早の最適化は...よく知っています。
Mathias Lykkegaard Lorenzen 2014

1
「最速.NET JSONシリアライザー」リンクは404ingです。さらに、この回答は5年半以上前のものです。さまざまな.NET JSONシリアライザーのパフォーマンスに関する更新はありますか?
ErikE 2016

11

これは2008年からのものであることに注意してください。今日、シリアライザを組み込む必要があり、swagger +属性を使用してエンドポイントについてコンシューマに通知し、データを返すことができると主張します。


匿名型をシリアル化するべきではないと主張します。私はここでの誘惑を知っています。緩やかな型の環境、つまりブラウザーのJavaScriptで使用される使い捨ての型をすばやく生成したい場合。それでも、実際のタイプを作成してSerializableとして装飾します。次に、Webメソッドを強く入力できます。これはJavascriptの1つのiotaには関係ありませんが、メソッドに自己文書化を追加します。ある程度経験のあるプログラマであれば、関数のシグネチャを見て、「ああ、これはタイプFooです。JSONでどのように見えるか知っています」と言うことができます。

そうは言っても、JSON.Netを試してシリアライズを行うことができます。それがうまくいくかどうかはわかりません


3
JSON.Netは問題なく動作します。私はあなたがすべきではないと主張します:)、私はそれが多くの場合かなり正当だと思います。
aprilchild、2008

2
「捨てる」タイプがMVCで使用されているのを見た後、私はいくつかの説得力のある使用法を見ることができます。.Netツールボックスに入れておくと、とても便利なツールだと思います。
マシューホワイト、

12
これは、特に消費のみのタイプの場合、私がまた柔らかくした点です。しかし、オブジェクトがサーバーに戻る場合、またはオブジェクトが複数の場所で使用されている場合でも、型を作成すると問題が少なくなると私は信じています。
Jason Jackson、

DataContractスタイルの逆シリアル化は、ポリモーフィック型を適切に処理しません。独自のデシリアライザを作成する必要があります。コードのメンテナンスが多すぎる。
micahhoover 2015年

匿名型のシリアル化が役立つユースケースは、Web APIの単体テストです。
howcheng 2016

9

私が見つけた最速の方法はこれです:

var obj = new {Id = thing.Id, Name = thing.Name, Age = 30};
JavaScriptSerializer serializer = new JavaScriptSerializer();
string json = serializer.Serialize(obj);

名前空間:System.Web.Script.Serialization.JavaScriptSerializer


2
そして逆シリアル化のために:。dynamic myObject = JsonConvert.DeserializeObject <dynamic>(出力); 。。参照:Newtonsoft.json.dll
i31nGo


1

これをWebサービスに使用していると仮定すると、次の属性をクラスに適用できます。

[System.Web.Script.Services.ScriptService]

次に、Jsonを返す各メソッドの次の属性:

[ScriptMethod(ResponseFormat = ResponseFormat.Json)]

そして、メソッドの戻り値の型を「オブジェクト」に設定します


標準のASP Webサービスの場合、[ScriptMethod(ResponseFormat = ResponseFormat.Json)]はメソッドで必要ありませんが、[WebMethod]が行います。また、戻り値の型をオブジェクトに設定しないでください。これは、複雑ではない(つまり、シリアル化できる)型で強く型付けできます。
row1 2010年

-1
public static class JsonSerializer
{
    public static string Serialize<T>(this T data)
    {
        try
        {
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
            var stream = new MemoryStream();
            serializer.WriteObject(stream, data);
            string jsonData = Encoding.UTF8.GetString(stream.ToArray(), 0, (int)stream.Length);
            stream.Close();
            return jsonData;
        }
        catch
        {
            return "";
        }
    }
    public static T Deserialize<T>(this string jsonData)
    {
        try
        {
            DataContractJsonSerializer slzr = new DataContractJsonSerializer(typeof(T));
            var stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonData));
            T data = (T)slzr.ReadObject(stream);
            stream.Close();
            return data;
        }
        catch
        {
            return default(T);
        }
    }
}

これは、質問のように匿名型をシリアル化しません
Mark Sowul
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.