私は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"
]
}
つかいます
var rootObject = JsonConvert.DeserializeObject<RootObject>(string json);
クラスを JSON 2 C# に作成します
Json.NETのドキュメント:Json.NETによるJSONのシリアライズとデシリアライズ
一般的なDeserializeObjectメソッドを使ってみましたか?
JsonConvert.DeserializeObject<MyAccount>(myjsondata);
JSONデータに欠けているフィールドは、単にNULLのままにしてください。
更新:
JSON文字列が配列の場合は、これを試してください。
var jarray = JsonConvert.DeserializeObject<List<MyAccount>>(myjsondata);
jarray
はList<MyAccount>
になります。
別のアップデート:
あなたが得ている例外はオブジェクトの配列と一致していません - シリアライザはあなたのDictionary型のaccountstatusmodifiedby
プロパティに問題があると思います。
accountstatusmodifiedby
プロパティをシリアライゼーションから除外し、それが役立つかどうかを確認してください。もしそうなら、あなたはその特性を異なって表現する必要があるかもしれません。
回答は https://stackoverflow.com/a/10718128/776476 から再作成されました
作業を簡単にするためにC#dynamic
型を使用できます。このテクニックはまた、魔法の文字列に頼らないのでリファクタリングをより簡単にします。
Json
以下のjson
文字列は、http api呼び出しからの単純な応答であり、2つのプロパティId
とName
を定義しています。
{"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;
を追加することを忘れないでください。
あなたが使用することができます:
JsonConvert.PopulateObject(json, obj);
ここで、json
はJSON文字列、obj
はターゲットオブジェクトです。参照してください: 例
注: PopulateObject()
は、Populate()
、obj's
リストメンバーに元のデータとjson文字列のデータが含まれるようになった後も、objのリストデータを消去しません。
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クラスジェネレータ を使用して生成されたクラスです。
これは私が使った設定のスクリーンショットで、 ウェブバージョン が説明できなかった奇妙なプロパティ名を考慮しています。
私は自分の物を間違って造ったことに気づいた。 JSONからオブジェクトクラスを生成するために http://json2csharp.com/ を使用しました。正しいOjectを取得したら、問題なくキャストできました。ノビット、ノブの間違い。あなたが同じ問題を抱えている場合は私はそれを追加すると思いました。
詳細については、いくつかのクラスジェネレータをオンラインで確認してみてください。しかし、私はいくつかの答えが役に立つと信じています。これが私のアプローチです。
次のコードは動的メソッドを念頭に置いて作成されました。
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文字列に含まれるメンバーにアクセスすることを可能にします。クラスを必要としない、ちょっと違う方法。 query
、trend
およびurl
は、Jsonストリングに含まれているオブジェクトです。
このWebサイト を使うこともできます。クラスを100%信頼しないでください、しかし、あなたはアイデアを得ます。
あなたのサンプルデータが正しいと仮定すると、あなたのgivenname、そして括弧で囲まれた他のエントリはJSの配列です...あなたはそれらのデータ型のためにListを使いたいでしょう。例えばaccountstatusexpmaxdateのリストなどです。あなたの例では日付のフォーマットが間違っていると思いますが、あなたの例で他に何が間違っているかは不明です。
これは古い投稿ですが、問題をメモしておきたかったのです。