3

着信 JSON アイテムを取得してリストボックス アイテムにバインドしようとしていますが、ビジュアル スタジオから、オブジェクトではなく配列を実行する必要があると言われました。私はこれを行う必要はありませんでした.誰も方法を知っていますか?

私のルートオブジェクト:

public class RootObject
{
    public string url { get; set; }
    public string display { get; set; }
    public List<string> genetics { get; set; }
    public List<string> price { get; set; }
    public List<string> brandMaker { get; set; }
    public string form { get; set; }
    public string dosornos { get; set; }
    public string qty { get; set; }
    public string mfg { get; set; }
    public string mobURI { get; set; }
}

注: Genetics、Price、BrandMaker は、実際には以下のような値以外は何も返しません。

"genetics": [
    "typeophere"
],
"price": [
    "$1400"
],

JSON ファイル/リクエストの基本的な結果:

  [
{
    "url": "N/A",
    "display": "",
    "genetics": [
        "microogiz"
    ],
    "price": [
        "96.016"
    ],
    "brandMaker": [
        "Oshi Kunti Multikashi, Osaka, JP"
    ],
    "form": "tangent",
    "dosornos": "n/a",
    "qty": "88G",
    "mfg": "SelfMade Industries, USA Dist.",
    "mobURI": "n/a"
}

]

私の元のコード:

// Get JSON via WEB
string ProviderURI = goURI;
webClient webClient = new WebClient();
webClient.DownloadStringCompleted += new  
    DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
webClient.DownloadStringAsync(new Uri(ProviderURI));

void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    if (e.Error != null)
    {
        return;
    }

    var deserializedJSON = JsonConvert.DeserializeObject<RootObject>(e.Result);
    lstBoxResults.ItemsSource = deserializedJSON; // or deserializedJSON.url.ToString();
}
4

2 に答える 2

13

遺伝学と価格は配列ですが、返される JSON には項目が 1 つしか含まれていません。RootObject の残りの部分は単純な文字列プロパティです。

生の JSON の例を投稿していないためです。物事をシンプルかつ短く保つために、縮小版を提示させてください.

{
    "url": "http://www.stackoverflow.com",
    "display": "This is a test",
    "genetics": [
        "typeophere"
    ],
    "price": [
        "$1400"
    ],
    "form": "a form"
}

これで、RootObject クラス タイプを切り詰めることができます。プロパティに Pascal ケーシングを使用し、それらを JSON.NET 属性に関連付けて、デシリアリング/シリアライズを支援しました。

[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class RootObject
{
    [JsonProperty(PropertyName = "url")]
    public string Url { get; set; }

    [JsonProperty(PropertyName = "display")]
    public string Display { get; set; }

    [JsonProperty(PropertyName = "genetics")]
    public List<string> Genetics { get; set; }

    [JsonProperty(PropertyName = "price")]
    public List<string> Price { get; set; }

    [JsonProperty(PropertyName = "form")]
    public string Form { get; set; }
}

あなたが呼び出している Web サービスがわからないので、この JSON をテキスト ファイルに保存しました。埋め込みリソースとしてマークし、そこから読み取ります。

string json;
var resource = Application.GetResourceStream(new Uri("json.txt", UriKind.Relative));
using (var reader = new StreamReader(resource.Stream))
{
    json = reader.ReadToEnd();
}

この部分を WebClient 呼び出しに置き換えるだけで、JSON データを取得できます。

これで、JSON を RootObject インスタンスに逆シリアル化できます。

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

宣伝どおりに動作します。これを ListBox コントロールにバインドする必要があります。ListBox インスタンスの ItemSource プロパティにカーソルを合わせると、コレクションにバインドできることがツールチップに示されていることがわかります。単一の rootObject はコレクションではありません。直接バインドすることはできません。

lstBoxResults.ItemsSource = rootObject;

これは機能しません。RootObject インスタンスを System.Collections.IEnumerable に変換することはできません。これは、ItemsSource が期待しているものです。

簡単に修正。コレクションを作りましょう。

lstBoxResults.ItemsSource = new List<RootObject> { rootObject };

これは、JSON データが 1 つの rootObject のみを返すことを前提としています。ListBox に表示される項目は 1 つだけです。

ここで、JSON データが RootObjects の配列を返すとします。たとえば、RootItems のコレクションを含む「items」という配列。

{
    "items": [
    {
    "url": "http://www.stackoverflow.com",
    "display": "This is a test",
    "genetics": [ "typeophere" ],
    "price": [ "$1400" ],
    "form": "a form"        
    },
    {
    "url": "https://github.com/geersch",
    "display": "This is another test",
    "genetics": [ "typeophere" ],
    "price": [ "$2000" ],
    "form": "another form"
    }]
}

これをデシリアリングするのも同様に簡単です。JSON.NET を使用して、RootObjects のコレクションを取得します。

var data = JObject.Parse(json)["items"];

コレクション (IEnumerable) に逆シリアル化します。

var rootObjects = JsonConvert.DeserializeObject<IEnumerable<RootObject>>(data.ToString());

すでに RootObject のコレクションを持っているので、自分で作成する必要はありません。ListBox に直接バインドできます。

lstBoxResults.ItemsSource = rootObjects;

受け取った JSON データが無効のようです。解析する直前に、有効な JSON オブジェクトになるように変更してください。

例えば:

json = json.Substring(json.IndexOf("[") + 1);
json = json.Substring(0, json.LastIndexOf("]"));
var rootObjects = JsonConvert.DeserializeObject<RootObject>(json);
于 2012-06-23T06:25:48.787 に答える
6

これを試して

RootObject rootObject;

if (json.startsWith("["))
{
  rootObject = JsonConvert.DeserializeObject<List<RootObject>>(json)[0];
}
else
{
  rootObject = JsonConvert.DeserializeObject<RootObject>(json);
}
于 2012-06-23T11:00:05.377 に答える