Newtonsoft(または多分LINQ to JSON?)を使用してJSON to .NETオブジェクトをデシリアライズする


318

Newtonsoftに関するいくつかの投稿があることを知っているので、うまくいけば、これは正確には繰り返されません... KazaaのAPIによって返されたJSONデータをある種の素敵なオブジェクトに変換しようとしています

WebClient client = new WebClient();
Stream stream = client.OpenRead("http://api.kazaa.com/api/v1/search.json?q=muse&type=Album");
StreamReader reader = new StreamReader(stream);

List<string> list = Newtonsoft.Json.JsonConvert.DeserializeObject<List<string>>(reader.Read().ToString());

foreach (string item in list)
{
    Console.WriteLine(item);
}

//Console.WriteLine(reader.ReadLine());
stream.Close();

そのJsonConvertラインは、私が試していた最新のものです...私はそれを完全には理解しておらず、皆さんに尋ねることによっていくつかのフットワークを排除することを望んでいました。私はもともとそれをディクショナリまたは何かに変換しようとしていました...そして実際、私はそこにいくつかの値を取得する必要があるので、ドキュメントで判断すると、おそらくNewtonsoftのLINQ to JSONがより良い選択でしょうか?考え/リンク?

JSON戻りデータの例を次に示します。

{
  "page": 1,
  "total_pages": 8,
  "total_entries": 74,
  "q": "muse",
  "albums": [
    {
      "name": "Muse",
      "permalink": "Muse",
      "cover_image_url": "http://image.kazaa.com/images/69/01672812 1569/Yaron_Herman_Trio/Muse/Yaron_Herman_Trio-Muse_1.jpg",
      "id": 93098,
      "artist_name": "Yaron Herman Trio"
    },
    {
      "name": "Muse",
      "permalink": "Muse",
      "cover_image_url": "htt p://image.kazaa.com/images/54/888880301154/Candy_Lo/Muse/Candy_Lo-Muse_1.jpg",
      "i d": 102702,
      "artist_name": "\u76e7\u5de7\u97f3"
    },
    {
      "name": "Absolution",
      "permalink": " Absolution",
      "cover_image_url": "http://image.kazaa.com/images/65/093624873365/Mus e/Absolution/Muse-Absolution_1.jpg",
      "id": 48896,
      "artist_name": "Muse"
    },
    {
      "name": "Ab solution",
      "permalink": "Absolution-2",
      "cover_image_url": "http://image.kazaa.com/i mages/20/825646911820/Muse/Absolution/Muse-Absolution_1.jpg",
      "id": 118573,
      "artist _name": "Muse"
    },
    {
      "name": "Black Holes And Revelations",
      "permalink": "Black-Holes-An d-Revelations",
      "cover_image_url": "http://image.kazaa.com/images/66/093624428466/ Muse/Black_Holes_And_Revelations/Muse-Black_Holes_And_Revelations_1.jpg",
      "id": 48813,
      "artist_name": "Muse"
    },
    {
      "name": "Black Holes And Revelations",
      "permalink": "Bla ck-Holes-And-Revelations-2",
      "cover_image_url": "http://image.kazaa.com/images/86/ 825646911486/Muse/Black_Holes_And_Revelations/Muse-Black_Holes_And_Revelations_1 .jpg",
      "id": 118543,
      "artist_name": "Muse"
    },
    {
      "name": "Origin Of Symmetry",
      "permalink": "Origin-Of-Symmetry",
      "cover_image_url": "http://image.kazaa.com/images/29/825646 912629/Muse/Origin_Of_Symmetry/Muse-Origin_Of_Symmetry_1.jpg",
      "id": 120491,
      "artis t_name": "Muse"
    },
    {
      "name": "Showbiz",
      "permalink": "Showbiz",
      "cover_image_url": "http: //image.kazaa.com/images/68/825646182268/Muse/Showbiz/Muse-Showbiz_1.jpg",
      "id": 60444,
      "artist_name": "Muse"
    },
    {
      "name": "Showbiz",
      "permalink": "Showbiz-2",
      "cover_imag e_url": "http://image.kazaa.com/images/50/825646912650/Muse/Showbiz/Muse-Showbiz_ 1.jpg",
      "id": 118545,
      "artist_name": "Muse"
    },
    {
      "name": "The Resistance",
      "permalink": "T he-Resistance",
      "cover_image_url": "http://image.kazaa.com/images/36/825646864836/ Muse/The_Resistance/Muse-The_Resistance_1.jpg",
      "id": 121171,
      "artist_name": "Muse"
    }
  ],
  "per_page": 10
}

私はもう少し読んで、NewtonsoftのLINQ to JSONがまさに私が欲しかったものだとわかりました... WebClient、Stream、StreamReader、およびNewtonsoftを使用して... JSONデータのKazaaにアクセスし、URLを抽出し、ファイルをダウンロードして、それを実行できます全部で7行のコードのように!大好きです。

WebClient client = new WebClient();
Stream stream = client.OpenRead("http://api.kazaa.com/api/v1/search.json?q=muse&type=Album");
StreamReader reader = new StreamReader(stream);

Newtonsoft.Json.Linq.JObject jObject = Newtonsoft.Json.Linq.JObject.Parse(reader.ReadLine());

// Instead of WriteLine, 2 or 3 lines of code here using WebClient to download the file
Console.WriteLine((string)jObject["albums"][0]["cover_image_url"]);
stream.Close();

この投稿には非常に多くのヒットがあり、コメントで説明されている「using」ビットを含めると役立つと思いました。

using(var client = new WebClient())
using(var stream = client.OpenRead("http://api.kazaa.com/api/v1/search.json?q=muse&type=Album"))
using (var reader = new StreamReader(stream))
{
    var jObject = Newtonsoft.Json.Linq.JObject.Parse(reader.ReadLine());
    Console.WriteLine((string) jObject["albums"][0]["cover_image_url"]);
}

6
滑らかな例、ありがとう。ただの提案です。簡潔にするために、これを省略した 可能性がありますがWebClientStreamStreamReaderすべてのが実装されているため、コードにIDisposableいくつかのusingブロックを追加することができます。
2011年

ええ、いい電話です...(yaこれは、実際には、私がこれからやって来るタスクを調査するために本当にすばやく実行しているコンソールアプリです)パズルの最後のピース、HLS + AES暗号化を調査します:) ugh ...笑
Jベンジャミン

1
+1 Linqの例を投稿していただきありがとうございます。まさに私が必要としたもの。
マークウィルキンス

newtonsoftソリューションはJSONも完全にデシリアライズしませんか?@arcainのソリューションと同じように。
AXMIM 2016年

ここのリンクに注意してください:LINQ to JSON
yu yang Jian

回答:


259

JSONオブジェクトからいくつかの項目を取得するだけの場合は、Json.NETのLINQ to JSON JObjectクラスを使用します。例えば:

JToken token = JObject.Parse(stringFullOfJson);

int page = (int)token.SelectToken("page");
int totalPages = (int)token.SelectToken("total_pages");

JSONオブジェクトを完全に逆シリアル化する必要がないため、このアプローチが気に入っています。これは、Twitterのように、オブジェクトのプロパティが不足していることに時々驚かされる可能性があるAPIで役立ちます。

ドキュメント:Json.NETを使用したJSONのシリアライズとデシリアライズ使用したJSONの使用したLINQ to JSON


1
ええ、私は実際にもう少し読んだりテストしたりしています...これもそれを行う良い方法であることがわかりました... Newtonsoft、かなりいいライブラリ、私は他の人のために私の例を投稿します
J Benjamin

1
私がそれをやっていた大まかな例を投稿しました...まったく同じではありません、JToken.Parseの提案を参照してください...
Jベンジャミン

1
@Jbenjaminありがとう!それはタイプミスでした。JTokenはJObjectの基本クラスであり、より抽象的な型で作業するのは私の個人的な好みにすぎません。私の注意を呼んでくれてありがとう。
2011年

申し訳ありませんが、それはJTokenまたはJObjectである必要がありますか?上記のコードはまだ時々エラー「JsonReaderからのJObjectの読み取りエラー」をスローしています。
TYRONEMICHAEL

1
@Tyroneもちろん、問題ありません。私は実際にこのコードをTwitterのステータス解析にも使用しています。Twitterの呼び出しは、ときどき不安定になる可能性があるため、かなりのエラー処理を記述しなければなりませんでした。まだ実行していない場合は、解析する前に、未加工のJSON応答をTwitterからログにダンプすることをお勧めします。その後、失敗した場合は、少なくともファンキーなものを受信したかどうかを確認できます。
アーケーン

272

あなたはC#を使うことができます dynamic型を物事を簡単にすることができます。この手法は、マジックストリングに依存しないため、リファクタリングも簡単になります。

JSON

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

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

C#

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

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

あなたはのタイプを指定した場合results、変数を通りdynamic、代わりに使用するvarキーワードを、そのプロパティの値が正しく例えば、デシリアライズされますIdintしていませんJValue(下記のコメントをGFoley83に感謝)。

:NewtonsoftアセンブリのNuGetリンクはhttp://nuget.org/packages/newtonsoft.jsonです。です。

パッケージ:nugetライブインストーラーを使用してパッケージを追加することもできます。プロジェクトを開いてパッケージ参照し、インストールしてインストール、アンインストール、更新するだけです。Dependencies / NuGetでプロジェクトに追加されます。


上記と同じコードを使用して、newtonsoft.dllバージョン4.5.6でTwitter応答をデシリアライズしましたが、正常に機能していましたが、バージョン5.0.6に更新した後、エラーが発生し始めました...なぜ ??
プラナフ2014

1
知っているか、c#クラスがある場合、動的オブジェクトに適しています。たとえば、<Myclass>のように、動的オブジェクトの置換時にC#クラスとして使用できます。
MSTdev 2015年

2
dynamic results = JsonConvert.DeserializeObject<ExpandoObject>(json);こちらのFTWをご利用ください。正しくIdではなく、intに逆シリアル化されJValueます。ここを参照してください:dotnetfiddle.net/b0WxGJ
GFoley83

@biofractal dynamic results = JsonConvert.DeserializeObject<dynamic>(json); VB.NETでこれをどのように実行しますか?Dim results As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(Of Object)(json)動作しません。
Flo


41

ではdynamic、キーワード、それはこの種の任意のオブジェクトを解析するために本当に簡単になり:

dynamic x = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonString);
var page = x.page;
var total_pages = x.total_pages
var albums = x.albums;
foreach(var album in albums)
{
    var albumName = album.name;

    // Access album data;
}

結果をループする方法を知りたかったのですが、これを見つけるのに時間がかかりすぎました...ありがとうございます!!
batoutofhell 2016

22

私が間違っている場合は修正してください。ただし、前の例は、James NewtonのJson.NETライブラリの最新バージョンとわずかに同期していないと思います。

var o = JObject.Parse(stringFullOfJson);
var page = (int)o["page"];
var totalPages = (int)o["total_pages"];

1
あなたの応答に感謝Rick、yaそれは私が最新のドキュメントでも見つけた例に似ています。
Jベンジャミン

1
うん、タイプミスを修正しarcainいるので、私のコメントは今ちょうどnitpickyになります:。。 "(私はJToken.Parseを認識しなかったので、私はもともと投稿
リック・リーチ

1
まったくつらいことではありません。間違いがあったことは間違いありません。それを行う方法は常に複数あります。ちなみに、私のバージョンのJson.NETはonのインデクサーを使用した構文をサポートしていますJObjectが、私の答えのために変更したコードは、SelectTokenメソッドのオーバーロードを使用するコードからプルされたので、トークンがなかった場合の例外を抑制できますが見つかりました:JToken JToken.SelectToken(string tokenName, bool errorWhenNoMatch)だから、そこから冗長性が生まれました。
アルカイン、2011年

18

私のように、強く型付けされたオブジェクトを扱いたい場合**

MyObj obj =  JsonConvert.DeserializeObject<MyObj>(jsonString);

このようにして、インテリセンスを使用し、コンパイル時のタイプのエラーチェックを行うことができます。

JSONをメモリにコピーしてJSONオブジェクトとして貼り付けることで、必要なオブジェクトを簡単に作成できます(Visual Studio-> Edit-> Paste Special-> Paste JSON as Classes)。

Visual Studioにそのオプションがない場合は、こちらを参照してください。

また、JSONが有効であることを確認する必要があります。オブジェクトの配列のみの場合は、最初に独自のオブジェクトを追加します。ie { "obj": [{}、{}、{}]}

** ダイナミックを使用すると物事が簡単になる場合があることは知っていますが、これは少し古臭いです。


1
私の好みはプログラミングへのアプローチです。強い型付けのオブジェクトが好きです。ありがとう、このコードを使用して修正した。
j.hull

11

緩やかに型付けされた動的リスト -値を逆シリアル化して読み取る

// First serializing
dynamic collection = new { stud = stud_datatable }; // The stud_datable is the list or data table
string jsonString = JsonConvert.SerializeObject(collection);


// Second Deserializing
dynamic StudList = JsonConvert.DeserializeObject(jsonString);

var stud = StudList.stud;
foreach (var detail in stud)
{
    var Address = detail["stud_address"]; // Access Address data;
}

8

私はこの方法が好きです:

using Newtonsoft.Json.Linq;
// jsonString is your JSON-formatted string
JObject jsonObj = JObject.Parse(jsonString);
Dictionary<string, object> dictObj = jsonObj.ToObject<Dictionary<string, object>>();

dictObj辞書として使用して、必要なものにアクセスできます。Dictionary<string, string>値を文字列として取得したい場合にも使用できます。

これと同じメソッドを使用して、あらゆる種類の.NETオブジェクトとしてキャストできます。


2
私はこの方法が2つの理由で非常に良いと思います:1)データ型を気にしないとき(すべてが文字列です)、および2)値のディクショナリを使用すると便利です
netfed

7

また、JSONコンテンツ内にネストされた特定の値を探しているだけの場合は、次のようにします。

yourJObject.GetValue("jsonObjectName").Value<string>("jsonPropertyName");

以降も同様です。

これは、JSON全体をC#オブジェクトに変換するコストを負担したくない場合に役立ちます。


2

私はjsonのExtionclassを作成しました:

 public static class JsonExtentions
    {
        public static string SerializeToJson(this object SourceObject) { return Newtonsoft.Json.JsonConvert.SerializeObject(SourceObject); }


        public static T JsonToObject<T>(this string JsonString) { return (T)Newtonsoft.Json.JsonConvert.DeserializeObject<T>(JsonString); }
}

デザインパターン:

 public class Myobject
    {
        public Myobject(){}
        public string prop1 { get; set; }

        public static Myobject  GetObject(string JsonString){return  JsonExtentions.JsonToObject<Myobject>(JsonString);}
        public  string ToJson(string JsonString){return JsonExtentions.SerializeToJson(this);}
    }

使用法:

   Myobject dd= Myobject.GetObject(jsonstring);

                 Console.WriteLine(dd.prop1);


1

このパーティーにはかなり遅れましたが、私は今日、自分でこの問題に出会いました。これが私が問題を解決した方法です。

書籍のリストを取得するためにサードパーティのAPIにアクセスしていました。オブジェクトは、約20以上のフィールドを含む大規模なJSONオブジェクトを返しましたが、そのリストIDオブジェクトはリスト文字列オブジェクトとしてのみ必要でした。動的オブジェクトでlinqを使用して、必要な特定のフィールドを取得し、それをリスト文字列オブジェクトに挿入しました。

dynamic content = JsonConvert.DeserializeObject(requestContent);
var contentCodes = ((IEnumerable<dynamic>)content).Where(p => p._id != null).Select(p=>p._id).ToList();

List<string> codes = new List<string>();

foreach (var code in contentCodes)
{
    codes.Add(code?.ToString());
}

0

最後にJSONから状態名を取得します

ありがとうございました!

Imports System
Imports System.Text
Imports System.IO
Imports System.Net
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
Imports System.collections.generic

Public Module Module1
    Public Sub Main()

         Dim url As String = "http://maps.google.com/maps/api/geocode/json&address=attur+salem&sensor=false"
            Dim request As WebRequest = WebRequest.Create(url)
        dim response As WebResponse = DirectCast(request.GetResponse(), HttpWebResponse)
        dim reader As New StreamReader(response.GetResponseStream(), Encoding.UTF8)
          Dim dataString As String = reader.ReadToEnd()

        Dim getResponse As JObject = JObject.Parse(dataString)

        Dim dictObj As Dictionary(Of String, Object) = getResponse.ToObject(Of Dictionary(Of String, Object))()
        'Get State Name
        Console.WriteLine(CStr(dictObj("results")(0)("address_components")(2)("long_name")))
    End Sub
End Module
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.