web-dev-qa-db-ja.com

JSON.NETを使用してJSONデータをC#にシリアル化解除する

私はC#とJSONデータを扱うことに比較的慣れておらず、ガイダンスを求めています。私はC#3.0、.NET 3.5 SP 1、およびJSON.NET 3.5 r 6を使用しています。

私はJSON構造から移入する必要がある定義されたC#クラスを持っています。ただし、Webサービスから取得されたエントリのすべてのJSON構造に、C#クラス内で定義されているすべての可能な属性が含まれているわけではありません。

私は間違った、難しい方法であるように思われていることをしていて、JObjectからそれぞれの値を一つずつ選び出し、そして文字列を目的のクラスプロパティに変換しています。

JsonSerializer serializer = new JsonSerializer();
var o = (JObject)serializer.Deserialize(myjsondata);

MyAccount.EmployeeID = (string)o["employeeid"][0];

JSON構造をC#クラスに逆シリアル化し、JSONソースからの可能性のある欠落データを処理するための最良の方法は何ですか?

私のクラスは次のように定義されています:

  public class MyAccount
  {

    [JsonProperty(PropertyName = "username")]
    public string UserID { get; set; }

    [JsonProperty(PropertyName = "givenname")]
    public string GivenName { get; set; }

    [JsonProperty(PropertyName = "sn")]
    public string Surname { get; set; }

    [JsonProperty(PropertyName = "passwordexpired")]
    public DateTime PasswordExpire { get; set; }

    [JsonProperty(PropertyName = "primaryaffiliation")]
    public string PrimaryAffiliation { get; set; }

    [JsonProperty(PropertyName = "affiliation")]
    public string[] Affiliation { get; set; }

    [JsonProperty(PropertyName = "affiliationstatus")]
    public string AffiliationStatus { get; set; }

    [JsonProperty(PropertyName = "affiliationmodifytimestamp")]
    public DateTime AffiliationLastModified { get; set; }

    [JsonProperty(PropertyName = "employeeid")]
    public string EmployeeID { get; set; }

    [JsonProperty(PropertyName = "accountstatus")]
    public string AccountStatus { get; set; }

    [JsonProperty(PropertyName = "accountstatusexpiration")]
    public DateTime AccountStatusExpiration { get; set; }

    [JsonProperty(PropertyName = "accountstatusexpmaxdate")]
    public DateTime AccountStatusExpirationMaxDate { get; set; }

    [JsonProperty(PropertyName = "accountstatusmodifytimestamp")]
    public DateTime AccountStatusModified { get; set; }

    [JsonProperty(PropertyName = "accountstatusexpnotice")]
    public string AccountStatusExpNotice { get; set; }

    [JsonProperty(PropertyName = "accountstatusmodifiedby")]
    public Dictionary<DateTime, string> AccountStatusModifiedBy { get; set; }

    [JsonProperty(PropertyName = "entrycreatedate")]
    public DateTime EntryCreatedate { get; set; }

    [JsonProperty(PropertyName = "entrydeactivationdate")]
    public DateTime EntryDeactivationDate { get; set; }

  }

そして解析するJSONのサンプルは次のとおりです。

{
    "givenname": [
        "Robert"
    ],
    "passwordexpired": "20091031041550Z",
    "accountstatus": [
        "active"
    ],
    "accountstatusexpiration": [
        "20100612000000Z"
    ],
    "accountstatusexpmaxdate": [
        "20110410000000Z"
    ],
    "accountstatusmodifiedby": {
        "20100214173242Z": "tdecker",
        "20100304003242Z": "jsmith",
        "20100324103242Z": "jsmith",
        "20100325000005Z": "rjones",
        "20100326210634Z": "jsmith",
        "20100326211130Z": "jsmith"
    },
    "accountstatusmodifytimestamp": [
        "20100312001213Z"
    ],
    "affiliation": [
        "Employee",
        "Contractor",
        "Staff"
    ],
    "affiliationmodifytimestamp": [
        "20100312001213Z"
    ],
    "affiliationstatus": [
        "detached"
    ],
    "entrycreatedate": [
        "20000922072747Z"
    ],
    "username": [
        "rjohnson"
    ],
    "primaryaffiliation": [
        "Staff"
    ],
    "employeeid": [
        "999777666"
    ],
    "sn": [
        "Johnson"
    ]
}
140
user305145

つかいます

var rootObject =  JsonConvert.DeserializeObject<RootObject>(string json);

クラスを JSON 2 C# に作成します


Json.NETのドキュメント:Json.NETによるJSONのシリアライズとデシリアライズ

271
w.donk

一般的なDeserializeObjectメソッドを使ってみましたか?

JsonConvert.DeserializeObject<MyAccount>(myjsondata);

JSONデータに欠けているフィールドは、単にNULLのままにしてください。

更新:

JSON文字列が配列の場合は、これを試してください。

var jarray = JsonConvert.DeserializeObject<List<MyAccount>>(myjsondata);

jarrayList<MyAccount>になります。

別のアップデート:

あなたが得ている例外はオブジェクトの配列と一致していません - シリアライザはあなたのDictionary型のaccountstatusmodifiedbyプロパティに問題があると思います。

accountstatusmodifiedbyプロパティをシリアライゼーションから除外し、それが役立つかどうかを確認してください。もしそうなら、あなたはその特性を異なって表現する必要があるかもしれません。

ドキュメント:Json.NETによるJSONのシリアライズとデシリアライズ

77
Dave Swersky

回答は https://stackoverflow.com/a/10718128/776476 から再作成されました

作業を簡単にするためにC#dynamic型を使用できます。このテクニックはまた、魔法の文字列に頼らないのでリファクタリングをより簡単にします。

Json

以下のjson文字列は、http api呼び出しからの単純な応答であり、2つのプロパティIdNameを定義しています。

{"Id": 1, "Name": "biofractal"}

C#

JsonConvert.DeserializeObject<dynamic>()を使用してこの文字列を動的な型に逆シリアル化してから、通常の方法でそのプロパティにアクセスします。

var results = JsonConvert.DeserializeObject<dynamic>(json);
var id = results.Id;
var name= results.Name;

:NewtonSoftアセンブリのNuGetリンクは http://nuget.org/packages/newtonsoft.json です。これらのクラスにアクセスするには、using Newtonsoft.Json;を追加することを忘れないでください。

49
biofractal

あなたが使用することができます:

JsonConvert.PopulateObject(json, obj);

ここで、jsonはJSON文字列、objはターゲットオブジェクトです。参照してください:

注: PopulateObject() は、Populate()obj'sリストメンバーに元のデータとjson文字列のデータが含まれるようになった後も、objのリストデータを消去しません。

8
bbants

Bbantの答えを基にして、これはリモートURLからJSONを逆シリアル化するための私の完全なソリューションです。

using Newtonsoft.Json;
using System.Net.Http;

namespace Base
{
    public class ApiConsumer<T>
    {
        public T data;
        private string url;

        public CalendarApiConsumer(string url)
        {
            this.url = url;
            this.data = getItems();
        }

        private T getItems()
        {
            T result = default(T);
            HttpClient client = new HttpClient();

            // This allows for debugging possible JSON issues
            var settings = new JsonSerializerSettings
            {
                Error = (sender, args) =>
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
            };

            using (HttpResponseMessage response = client.GetAsync(this.url).Result)
            {
                if (response.IsSuccessStatusCode)
                {
                    result = JsonConvert.DeserializeObject<T>(response.Content.ReadAsStringAsync().Result, settings);
                }
            }
            return result;
        }
    }
}

使い方は次のようになります。

ApiConsumer<FeedResult> feed = new ApiConsumer<FeedResult>("http://example.info/feeds/feeds.aspx?alt=json-in-script");

FeedResultは、 Xamasoft JSONクラスジェネレータ を使用して生成されたクラスです。

これは私が使った設定のスクリーンショットで、 ウェブバージョン が説明できなかった奇妙なプロパティ名を考慮しています。

Xamasoft JSON Class Generator

3
Kyle Falconer

私は自分の物を間違って造ったことに気づいた。 JSONからオブジェクトクラスを生成するために http://json2csharp.com/ を使用しました。正しいOjectを取得したら、問題なくキャストできました。ノビット、ノブの間違い。あなたが同じ問題を抱えている場合は私はそれを追加すると思いました。

1
Adam

詳細については、いくつかのクラスジェネレータをオンラインで確認してみてください。しかし、私はいくつかの答えが役に立つと信じています。これが私のアプローチです。

次のコードは動的メソッドを念頭に置いて作成されました。

dynObj = (JArray)JsonConvert.DeserializeObject(nvm);

        foreach (JObject item in dynObj)
        {
            foreach (JObject trend in item["trends"])
            {
         Console.WriteLine("{0}-{1}-{2}", trend["query"], trend["name"], trend["url"]);

            }
        }

このコードは基本的にあなたがJson文字列に含まれるメンバーにアクセスすることを可能にします。クラスを必要としない、ちょっと違う方法。 querytrendおよびurlは、Jsonストリングに含まれているオブジェクトです。

このWebサイト を使うこともできます。クラスを100%信頼しないでください、しかし、あなたはアイデアを得ます。

1
Edward Newgate

あなたのサンプルデータが正しいと仮定すると、あなたのgivenname、そして括弧で囲まれた他のエントリはJSの配列です...あなたはそれらのデータ型のためにListを使いたいでしょう。例えばaccountstatusexpmaxdateのリストなどです。あなたの例では日付のフォーマットが間違っていると思いますが、あなたの例で他に何が間違っているかは不明です。

これは古い投稿ですが、問題をメモしておきたかったのです。

0
Tracker1