JSON反序列化 - 处理可以是数组的属性

时间:2015-11-22 18:58:10

标签: c# json json.net

问题背景:

我正在查询Amazons产品广告API,并尝试将JSON响应取消激活到C#对象。

问题:

代码尝试转换时收到反序列化错误。我无法解决哪个部分导致错误。以下是我收到的错误:

Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type'System.Collections.Generic.List`1[ShoppingComparisonEngine.AWS.AwsCommon.Item]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.

To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.

Path 'Items.Item.ASIN', line 1, position 612.

代码:

以下C#是Newtonsoft尝试序列化的内容。

Item.cs:

public class Item
{
    [JsonProperty("asin")]
    public string ASIN { get; set; }
    [JsonProperty("parentasin")]
    public string ParentASIN { get; set; }
    [JsonProperty("detailpageurl")]
    public string DetailPageURL { get; set; }
    [JsonProperty("salesrank")]
    public string SalesRank { get; set; }
    [JsonProperty("smallimage")]
    public SmallImage SmallImage { get; set; }
    [JsonProperty("mediumimage")]
    public MediumImage MediumImage { get; set; }
    [JsonProperty("largeimage")]
    public LargeImage LargeImage { get; set; }
    [JsonProperty("imagesets")]
    public ImageSets ImageSets { get; set; }
    [JsonProperty("itemattributes")]
    public ItemAttributes ItemAttributes { get; set; }
    [JsonProperty("offersummary")]
    public OfferSummary OfferSummary { get; set; }
    [JsonProperty("offers")]
    public Offers Offers { get; set; }
}

Items.cs:

    public class Items
{
    [JsonProperty("totalresults")]
    public string TotalResults { get; set; }
    [JsonProperty("totalpages")]
    public string TotalPages { get; set; }
    [JsonProperty("moresearchresultsurl")]
    public string MoreSearchResultsUrl { get; set; }
    [JsonProperty("item")]
    public List<Item> Item { get; set; }
}

JSON:

我认为这是一个问题,因为我有一个单一的项目,而转换需要一个列表?

{
"Items": {
    "xmlns": "http://webservices.amazon.com/AWSECommerceService/2011-08-01",
    "Request": {
        "IsValid": "True",
        "ItemSearchRequest": {
            "Availability": "Available",
            "Condition": "New",
            "ItemPage": "6",
            "Keywords": "champagne bucket",
            "ResponseGroup": [
                "Medium",
                "Offers"
            ],
            "SearchIndex": "HomeGarden"
        }
    },
    "TotalResults": "51",
    "TotalPages": "6",
    "MoreSearchResultsUrl": "http://www.amazon.co.uk/gp/redirect.html?linkCode=xm2&SubscriptionId=AKIAIFERUZJXWJ3Y2USA&location=http%3A%2F%2Fwww.amazon.co.uk%2Fgp%2Fsearch%3Fkeywords%3Dchampagne%2Bbucket%26url%3Dsearch-alias%253Doutdoor&tag=compar0c2-21&creative=12734&camp=2025",
    "Item": {
        "ASIN": "B00IYO4HRQ",
        "DetailPageURL": "http://www.amazon.co.uk/Bottle-Holder-Accessories-Garden-Maintenance/dp/B00IYO4HRQ%3FSubscriptionId%3DAKIAIFERUZJXWJ3Y2USA%26tag%3Dcompar0c2-21%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3DB00IYO4HRQ",
        "ItemLinks": {
            "ItemLink": [
                {
                    "Description": "Add To Wishlist",
                    "URL": "http://www.amazon.co.uk/gp/registry/wishlist/add-item.html%3Fasin.0%3DB00IYO4HRQ%26SubscriptionId%3DAKIAIFERUZJXWJ3Y2USA%26tag%3Dcompar0c2-21%26linkCode%3Dxm2%26camp%3D2025%26creative%3D12734%26creativeASIN%3DB00IYO4HRQ"
                },
                {
                    "Description": "Tell A Friend",
                    "URL": "http://www.amazon.co.uk/gp/pdp/taf/B00IYO4HRQ%3FSubscriptionId%3DAKIAIFERUZJXWJ3Y2USA%26tag%3Dcompar0c2-21%26linkCode%3Dxm2%26camp%3D2025%26creative%3D12734%26creativeASIN%3DB00IYO4HRQ"
                },
                {
                    "Description": "All Customer Reviews",
                    "URL": "http://www.amazon.co.uk/review/product/B00IYO4HRQ%3FSubscriptionId%3DAKIAIFERUZJXWJ3Y2USA%26tag%3Dcompar0c2-21%26linkCode%3Dxm2%26camp%3D2025%26creative%3D12734%26creativeASIN%3DB00IYO4HRQ"
                },
                {
                    "Description": "All Offers",
                    "URL": "http://www.amazon.co.uk/gp/offer-listing/B00IYO4HRQ%3FSubscriptionId%3DAKIAIFERUZJXWJ3Y2USA%26tag%3Dcompar0c2-21%26linkCode%3Dxm2%26camp%3D2025%26creative%3D12734%26creativeASIN%3DB00IYO4HRQ"
                }
            ]
        },
        "SmallImage": {
            "URL": "http://ecx.images-amazon.com/images/I/31cr9r7XChL._SL75_.jpg",
            "Height": {
                "Units": "pixels",
                "value": "75"
            },
            "Width": {
                "Units": "pixels",
                "value": "75"
            }
        },
        "MediumImage": {
            "URL": "http://ecx.images-amazon.com/images/I/31cr9r7XChL._SL160_.jpg",
            "Height": {
                "Units": "pixels",
                "value": "160"
            },
            "Width": {
                "Units": "pixels",
                "value": "160"
            }
        },
        "LargeImage": {
            "URL": "http://ecx.images-amazon.com/images/I/31cr9r7XChL.jpg",
            "Height": {
                "Units": "pixels",
                "value": "300"
            },
            "Width": {
                "Units": "pixels",
                "value": "300"
            }
        },
        "ImageSets": {
            "ImageSet": [
                {
                    "Category": "swatch",
                    "SwatchImage": {
                        "URL": "http://ecx.images-amazon.com/images/I/31lBLzzkQlL._SL30_.jpg",
                        "Height": {
                            "Units": "pixels",
                            "value": "30"
                        },
                        "Width": {
                            "Units": "pixels",
                            "value": "30"
                        }
                    },
                    "SmallImage": {
                        "URL": "http://ecx.images-amazon.com/images/I/31lBLzzkQlL._SL75_.jpg",
                        "Height": {
                            "Units": "pixels",
                            "value": "75"
                        },
                        "Width": {
                            "Units": "pixels",
                            "value": "75"
                        }
                    },
                    "ThumbnailImage": {
                        "URL": "http://ecx.images-amazon.com/images/I/31lBLzzkQlL._SL75_.jpg",
                        "Height": {
                            "Units": "pixels",
                            "value": "75"
                        },
                        "Width": {
                            "Units": "pixels",
                            "value": "75"
                        }
                    },
                    "TinyImage": {
                        "URL": "http://ecx.images-amazon.com/images/I/31lBLzzkQlL._SL110_.jpg",
                        "Height": {
                            "Units": "pixels",
                            "value": "110"
                        },
                        "Width": {
                            "Units": "pixels",
                            "value": "110"
                        }
                    },
                    "MediumImage": {
                        "URL": "http://ecx.images-amazon.com/images/I/31lBLzzkQlL._SL160_.jpg",
                        "Height": {
                            "Units": "pixels",
                            "value": "160"
                        },
                        "Width": {
                            "Units": "pixels",
                            "value": "160"
                        }
                    },
                    "LargeImage": {
                        "URL": "http://ecx.images-amazon.com/images/I/31lBLzzkQlL.jpg",
                        "Height": {
                            "Units": "pixels",
                            "value": "300"
                        },
                        "Width": {
                            "Units": "pixels",
                            "value": "300"
                        }
                    }
                },
                {
                    "Category": "primary",
                    "SwatchImage": {
                        "URL": "http://ecx.images-amazon.com/images/I/31cr9r7XChL._SL30_.jpg",
                        "Height": {
                            "Units": "pixels",
                            "value": "30"
                        },
                        "Width": {
                            "Units": "pixels",
                            "value": "30"
                        }
                    },
                    "SmallImage": {
                        "URL": "http://ecx.images-amazon.com/images/I/31cr9r7XChL._SL75_.jpg",
                        "Height": {
                            "Units": "pixels",
                            "value": "75"
                        },
                        "Width": {
                            "Units": "pixels",
                            "value": "75"
                        }
                    },
                    "ThumbnailImage": {
                        "URL": "http://ecx.images-amazon.com/images/I/31cr9r7XChL._SL75_.jpg",
                        "Height": {
                            "Units": "pixels",
                            "value": "75"
                        },
                        "Width": {
                            "Units": "pixels",
                            "value": "75"
                        }
                    },
                    "TinyImage": {
                        "URL": "http://ecx.images-amazon.com/images/I/31cr9r7XChL._SL110_.jpg",
                        "Height": {
                            "Units": "pixels",
                            "value": "110"
                        },
                        "Width": {
                            "Units": "pixels",
                            "value": "110"
                        }
                    },
                    "MediumImage": {
                        "URL": "http://ecx.images-amazon.com/images/I/31cr9r7XChL._SL160_.jpg",
                        "Height": {
                            "Units": "pixels",
                            "value": "160"
                        },
                        "Width": {
                            "Units": "pixels",
                            "value": "160"
                        }
                    },
                    "LargeImage": {
                        "URL": "http://ecx.images-amazon.com/images/I/31cr9r7XChL.jpg",
                        "Height": {
                            "Units": "pixels",
                            "value": "300"
                        },
                        "Width": {
                            "Units": "pixels",
                            "value": "300"
                        }
                    }
                }
            ]
        },
        "ItemAttributes": {
            "Brand": "Garden at Home",
            "EAN": "5971458914919",
            "EANList": {
                "EANListElement": "5971458914919"
            },
            "Feature": "Wine Bottle Holder and Cooler Bag Wine Accessories",
            "Label": "Outdoor&Lawn",
            "Manufacturer": "Outdoor&Lawn",
            "MPN": "GG_89773368",
            "PartNumber": "GG_89773368",
            "ProductGroup": "Lawn & Patio",
            "ProductTypeName": "OUTDOOR_LIVING",
            "Publisher": "Outdoor&Lawn",
            "Studio": "Outdoor&Lawn",
            "Title": "Wine Bottle Holder and Cooler Bag Wine Accessories, Garden, Lawn, Maintenance"
        },
        "OfferSummary": {
            "LowestNewPrice": {
                "Amount": "5220",
                "CurrencyCode": "GBP",
                "FormattedPrice": "£52.20"
            },
            "TotalNew": "1",
            "TotalUsed": "0",
            "TotalCollectible": "0",
            "TotalRefurbished": "0"
        },
        "Offers": {
            "TotalOffers": "1",
            "TotalOfferPages": "1",
            "MoreOffersUrl": "http://www.amazon.co.uk/gp/offer-listing/B00IYO4HRQ%3FSubscriptionId%3DAKIAIFERUZJXWJ3Y2USA%26tag%3Dcompar0c2-21%26linkCode%3Dxm2%26camp%3D2025%26creative%3D12734%26creativeASIN%3DB00IYO4HRQ",
            "Offer": {
                "OfferAttributes": {
                    "Condition": "New"
                },
                "OfferListing": {
                    "OfferListingId": "kif7varXuUaD7y55JfdjU7h3YCJvQokyXfgDIWvxOx6%2FqiMbxoPBsyFWCmgo8pbOqZNcezFUCBSdlx3JtRpEpe4Tu7VGv9zncLOYVmoSOUEDNQf1rrKJzZVCjnVPRCKyes0GSlEzlx%2Faht4%2FtjijlvCo14Z3CCcm",
                    "Price": {
                        "Amount": "5800",
                        "CurrencyCode": "GBP",
                        "FormattedPrice": "£58.00"
                    },
                    "SalePrice": {
                        "Amount": "5220",
                        "CurrencyCode": "GBP",
                        "FormattedPrice": "£52.20"
                    },
                    "AmountSaved": {
                        "Amount": "580",
                        "CurrencyCode": "GBP",
                        "FormattedPrice": "£5.80"
                    },
                    "PercentageSaved": "10",
                    "Availability": "Usually dispatched within 1-2 business days",
                    "AvailabilityAttributes": {
                        "AvailabilityType": "now",
                        "MinimumHours": "24",
                        "MaximumHours": "48"
                    },
                    "IsEligibleForSuperSaverShipping": "0",
                    "IsEligibleForPrime": "0"
                }
            }
        },
        "EditorialReviews": {
            "EditorialReview": {
                "Source": "Product Description",
                "Content": "Ice Bucket Bag and Wine Cooler This unique Ice Bucket Bag is attractive and very durable. It is ideal for transporting wine to a friend, hostess or party and arriving with it perfectly chilled.Transparent and waterproof, this wine or Champagne bag also makes a super, space-saving ice bucket that simply folds away after use. It is especially ideal for a picnic or BBQ as it can fold for easy transport and is unbreakableIn addition, this bag makes a great party favor - comes with pocket for place card, business card or gift card. Heavy duty plastic measures 4\" x 4\" x 10\" when open, gift card slot measures 2\" x 3\".",
                "IsLinkSuppressed": "0"
            }
        }
    }
}

修改

这是我用来创建一个转换器来处理单个Item对象和它们List的代码。

   public class ItemConverter:JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.StartArray)
        {
            List<Item> items =  serializer.Deserialize<List<Item>>(reader);

            return items;
        }
        else
        {
            Item itemList = serializer.Deserialize<Item>(reader);
            return new List<Item>(new[] { itemList });
        }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

2 个答案:

答案 0 :(得分:2)

.Net小提琴:https://dotnetfiddle.net/9MACjN

您有多个问题:

  • 您实际上错过了json中的结束}

  • 您需要反序列化为包含Response的父类(例如Items)。

  • Items.Item属性必须是Item类型,而不是List<Item>,正如David所说。

  • JsonProperty属性根本不需要。

然后它有效。

答案 1 :(得分:2)

JSON中的Item属性是普通对象,而不是对象列表。如果它应该是一个列表,那么JSON将用方括号括起来表示它是一个数组,例如:

"Item": [{ item1 }, { item2}, ... ]

因此您需要更改模型以匹配。例如:

public class Items
{
    //snip
    public Item Item { get; set; }
}