19

-serviceJSONから返されたものがMovie-objectsのリストを返し、すべてが大量の情報で特定されている状況があります。RESTそのREST-service結果のいくつかのフィールドは、利用可能な情報に応じて変化します。

例:映画には常にいくつかのスクリーンキャプチャ(画像)、俳優、監督がいます。問題の映画によっては、1つ以上の画像、1つ以上の俳優、1つ以上の監督がいる場合があります。いくつかのケースのサンプルJSON:

{
    "title": "Movie title",
    "images": [
        "http://www.url.com/img_0.jpg",
        "http://www.url.com/img_1.jpg",
        "http://www.url.com/img_2.jpg",
        "http://www.url.com/img_3.jpg",
        "http://www.url.com/img_4.jpg"
    ],
    "actors": [
        "Steven Berkoff",
        "Nikolaj Coster-Waldau",
        "Julie Cox"
    ],
    "directors": "Simon Aeby"
},
{
    "title": "Another movie",
    "images": "http://www.url.com/img_1.jpg",
    "actors": "actor 1"
    "directors": [
        "Justin Bieber",
        "Justin Timberlake"
    ]
}

問題は、JSON.netを使用して、この問題を処理するコンバーターを作成するにはどうすればよいですか?私はインターネットを精査してきましたが、まだ解決策を見つけていません。

同じ質問の別のスピン:フィールドが文字列のリストまたは単純な文字列のいずれかである場合、JSON.NETにいずれかの方法でリストを作成させるにはどうすればよいですか(単純な文字列の場合は、1つのメンバーでリストを作成します)

編集:このRESTサービスは私の制御不能です

4

2 に答える 2

11

わかりました、私は楽しみのためにそれをしました、しかしとにかく、有用であるか、または最良の方法であるとは思わない...

「動的」属性をオブジェクトとして宣言してから、ImagesAsListやImagesAsStringなどのプロパティを取得するメソッドを作成します。私は拡張メソッドでそれをしました.....

var movies = JsonConvert.DeserializeObject<List<Movie>>(str);

クラス

class Movie
{

    [JsonProperty("title")]
    public string Title { get; set; }

    [JsonProperty("images")]
    public object Images { get; set; }

    [JsonProperty("actors")]
    public object Actor { get; set; }

    [JsonProperty("directors")]
    public object Directors { get; set; }
}

拡張メソッド

static class MovieExtension
{
    public static List<string> ImagesAsList(this Movie m)
    {
        var jArray = (m.Images as JArray);
        if (jArray == null) return null;

        return jArray.Select(x => x.ToString()).ToList();
    }

    public static string ImagesAsString(this Movie m)
    {
        return m.Images as string;
    }

}

編集

@yamenのコメントを読んだ後、私は次のようないくつかの変更を行いました。

var settings = new JsonSerializerSettings();
settings.Converters.Add(new MoviesConverter());

var movies = JsonConvert.DeserializeObject<List<Movie>>(str, settings);

クラス

class Movie
{

    [JsonProperty("title")]
    public List<string> Title { get; set; }

    [JsonProperty("images")]
    public List<string> Images { get; set; }

    [JsonProperty("actors")]
    public List<string> Actor { get; set; }

    [JsonProperty("directors")]
    public List<string> Directors { get; set; }
}

コンバータ

class MoviesConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(string)) || (objectType == typeof(List<string>)) ;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.StartArray)
        {
            var l = new List<string>();
            reader.Read();
            while (reader.TokenType != JsonToken.EndArray)
            {
                l.Add(reader.Value as string);

                reader.Read();
            }
            return l;
        }
        else
        {
            return new List<string> { reader.Value as string };
        }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        //ToDo here we can decide to write the json as 
        //if only has one attribute output as string if it has more output as list
    }
}
于 2012-04-12T11:06:45.907 に答える
4

オブジェクトに直接シリアル化することはできませんが、あまり労力をかけずに手動でシリアル化することはできます。JSON.Netには、LINQtoJSONが含まれています。最初に、基になるJSONが配列でない場合でも、常にタイプTのリストを返すメソッドを定義します。

public List<T> getSingleOrArray<T>(JToken token)
{
    if (token.HasValues)
    {
        return token.Select(m => m.ToObject<T>()).ToList();
    }
    else
    {
        return new List<T> { token.ToObject<T>() };
    }
}

使用例:

JObject m1 = JObject.Parse(@"{
""title"": ""Movie title"",
""images"": [
    ""http://www.url.com/img_0.jpg"",
    ""http://www.url.com/img_1.jpg""
],
""actors"": [
    ""Steven Berkoff"",
    ""Julie Cox""
],
""directors"": ""Simon Aeby""
}");

JObject m2 = JObject.Parse(@"{
""title"": ""Another movie"",
""images"": ""http://www.url.com/img_1.jpg"",
""actors"": ""actor 1"",
""directors"": [
    ""Justin Bieber"",
    ""Justin Timberlake""
]
}");

IList<String> m1_directors = getSingleOrArray<string>(m1["directors"]);
IList<String> m2_directors = getSingleOrArray<string>(m2["directors"]);

m1_directoryは単一の要素を持つリストであり、m2_directorsは2つの要素を持つリストです。

于 2012-04-12T11:05:03.237 に答える