[解決済み] HTTPClient .ReadAsAsync で JSON を配列またはリストにデシリアライズする .NET 4.0 Task パターン
質問
から返されたJSONをデシリアライズしようとしています。
http://api.usa.gov/jobs/search.json?query=nursing+jobs
から返されたJSONを.NET 4.0 Taskパターンを使用してデシリアライズしようとしています。 このJSONを返します(「JSONデータを読み込む」 @
http://jsonviewer.stack.hu/
).
[
{
"id": "usajobs:353400300",
"position_title": "Nurse",
"organization_name": "Indian Health Service",
"rate_interval_code": "PA",
"minimum": 42492,
"maximum": 61171,
"start_date": "2013-10-01",
"end_date": "2014-09-30",
"locations": [
"Gallup, NM"
],
"url": "https://www.usajobs.gov/GetJob/ViewDetails/353400300"
},
{
"id": "usajobs:359509200",
"position_title": "Nurse",
"organization_name": "Indian Health Service",
"rate_interval_code": "PA",
"minimum": 42913,
"maximum": 61775,
"start_date": "2014-01-16",
"end_date": "2014-12-31",
"locations": [
"Gallup, NM"
],
"url": "https://www.usajobs.gov/GetJob/ViewDetails/359509200"
},
...
]
インデックスアクションです。
public class HomeController : Controller
{
public ActionResult Index()
{
Jobs model = null;
var client = new HttpClient();
var task = client.GetAsync("http://api.usa.gov/jobs/search.json?query=nursing+jobs")
.ContinueWith((taskwithresponse) =>
{
var response = taskwithresponse.Result;
var jsonTask = response.Content.ReadAsAsync<Jobs>();
jsonTask.Wait();
model = jsonTask.Result;
});
task.Wait();
...
}
ジョブ、ジョブクラス
[JsonArray]
public class Jobs { public List<Job> JSON; }
public class Job
{
[JsonProperty("organization_name")]
public string Organization { get; set; }
[JsonProperty("position_title")]
public string Title { get; set; }
}
にブレークポイントを設定すると
jsonTask.Wait();
にブレークポイントを設定し
jsonTask
を調べると、ステータスは
失敗しました。 InnerExceptionは"Type ProjectName.Jobs is not a collection.".です。
JsonArray属性なしのJobs型で、Jobsを配列(Job[])で起動したところ、このようなエラーが発生しました。
public class Jobs { public Job[] JSON; }
+ InnerException {"Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'ProjectName.Models.Jobs' because the type requires a JSON object (e.g. {\"name\":\"value\"}) to deserialize correctly.\r\n
To fix this error either change the JSON to a JSON object (e.g. {\"name\":\"value\"}) or change the deserialized type to an array or a type that implements a collection interface
(e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.\r\n
Path '', line 1, position 1."} System.Exception {Newtonsoft.Json.JsonSerializationException}
このサイトのJSONを.NET 4.0 Taskパターンで処理するにはどうしたらよいでしょうか。 これを動作させる前に
await async
パターンに移行する前に、これを動作させたいと思います。
ANSWER UPDATEです。
.NET 4.5のasync awaitパターンを使った例とbrumScouseの回答です。
public async Task<ActionResult>Index()
{
List<Job> model = null;
var client = newHttpClient();
// .NET 4.5 async await pattern
var task = await client.GetAsync(http://api.usa.gov/jobs/search.json?query=nursing+jobs);
var jsonString = await task.Content.ReadAsStringAsync();
model = JsonConvert.DeserializeObject<List<Job>>(jsonString);
returnView(model);
}
を持ってくる必要があります。
System.Threading.Tasks
という名前空間があります。
注意
はありません。
.ReadAsString
メソッドはありません。
.Content
を使用したのはそのためです。
.ReadAsStringAsync
メソッドを使用します。
どのように解決するのですか?
モデルを手作業で作成する代わりに、Json2csharp.comのウェブサイトのようなものを使用してみてください。 JSON 応答の例 (完全であればあるほど良い) を貼り付け、その結果生成されたクラスを取り込みます。 これは、少なくとも、いくつかの可動部分を取り除き、シリアライザに簡単な時間を与えるcsharpのJSONの形状を取得し、あなたは属性を追加する必要がないはずです。
ただ、それを動作させ、そして、あなたの命名規則に適合するように、クラス名を修正し、後で属性を追加してください。
EDIT 少しいじった後、結果を仕事のリストにデシリアライズすることに成功しました(Json2csharp.comを使用してクラスを作成しました)。
public class Job
{
public string id { get; set; }
public string position_title { get; set; }
public string organization_name { get; set; }
public string rate_interval_code { get; set; }
public int minimum { get; set; }
public int maximum { get; set; }
public string start_date { get; set; }
public string end_date { get; set; }
public List<string> locations { get; set; }
public string url { get; set; }
}
そして、コードの編集です。
List<Job> model = null;
var client = new HttpClient();
var task = client.GetAsync("http://api.usa.gov/jobs/search.json?query=nursing+jobs")
.ContinueWith((taskwithresponse) =>
{
var response = taskwithresponse.Result;
var jsonString = response.Content.ReadAsStringAsync();
jsonString.Wait();
model = JsonConvert.DeserializeObject<List<Job>>(jsonString.Result);
});
task.Wait();
これは、含んでいるオブジェクトを取り除くことができることを意味します。 これはTask関連の問題ではなく、むしろデシリアライズの問題であることに注目すべきです。
EDIT 2:
JSONオブジェクトを取り込んで、Visual Studioでクラスを生成する方法があります。 JSONをコピーして、Edit> Paste Special > Paste JSON as Classesとするだけです。ページ全体がここでこれに費やされています。
http://blog.codeinside.eu/2014/09/08/Visual-Studio-2013-Paste-Special-JSON-And-Xml/
関連
-
[解決済み] 保護レベルによりアクセス不能になりました。
-
[解決済み】パディングが無効で、削除できない?
-
[解決済み】IntPtrとは一体何なのか?
-
[解決済み] 関数を終了するには?
-
[解決済み] Json.netを使用してJSONオブジェクトを動的オブジェクトにデシリアライズする。
-
[解決済み] .NET NewtonSoft JSONのデシリアライズマップを異なるプロパティ名に変更する。
-
[解決済み】Newtonsoftを使用してJSONを.NETオブジェクトにデシリアライズする(またはLINQ to JSONかも?)
-
[解決済み】C#でJSONをデシリアライズする。
-
[解決済み] UnityでJsonとJson Arrayをシリアライズ/デシリアライズする
-
[解決済み] .net 4.5のHttpClientでレスポンスからクッキーを取得するのに苦労しています。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] [Entity Framework 4.1でエンティティに関連オブジェクトを追加する際に、エンティティオブジェクトをIEntityChangeTracker.の複数のインスタンスから参照できない。
-
[解決済み】文字列が有効な DateTime " format dd/MM/yyyy " として認識されなかった。
-
[解決済み】「入力文字列が正しい形式ではありませんでした」エラーの解決方法は?[重複しています]。
-
[解決済み】Visual Studio: 操作を完了できませんでした。パラメータが正しくありません
-
[解決済み】2つ(またはそれ以上)のリストを1つに統合する(C# .NETで
-
[解決済み】aspNetCore 2.2.0 - AspNetCoreModuleV2 エラー
-
[解決済み】ファイルやアセンブリ、またはその依存関係の1つをロードできませんでした。
-
[解決済み】WebResource.axdとは何ですか?
-
[解決済み】Nullableオブジェクトは値を持たなければならない?
-
[解決済み] 'System.Net.Http.HttpContent' に 'ReadAsAsync' の定義がなく、拡張メソッドもありません。