[英]Cannot deserialize the current JSON array into type from when response is xml
I have the following response xml format from Microsoft:我有以下来自 Microsoft 的响应 xml 格式:
<SuggestResponse xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Query>state of decay 2</Query>
<ResultSets>
<SuggestResults>
<Source>dcatall-products</Source>
<FromCache>false</FromCache>
<Type>product</Type>
<Suggests>
<Product>
<Curated>false</Curated>
<Source>Games</Source>
<Title>State of Decay 2</Title>
<Url>//www.microsoft.com/en-us/store/p/state-of-decay-2/9nt4x7p8b9nb</Url>
<ImageUrl>//store-images.s-microsoft.com/image/apps.47366.14425140369408817.dca0bcd1-c06c-4345-8a00-fe5bfaff3665.45f69514-da1a-43cd-a1ec-109fe5e54d24?w=150&h=150</ImageUrl>
<Metas>
<Meta>
<Key>BigCatalogId</Key>
<Value>9NT4X7P8B9NB</Value>
</Meta>
<Meta>
<Key>ProductType</Key>
<Value>Game</Value>
</Meta>
<Meta>
<Key>Icon</Key>
<Value>//store-images.s-microsoft.com/image/apps.47366.14425140369408817.dca0bcd1-c06c-4345-8a00-fe5bfaff3665.45f69514-da1a-43cd-a1ec-109fe5e54d24</Value>
</Meta>
<Meta>
<Key>ImageHeight</Key>
<Value>300</Value>
</Meta>
<Meta>
<Key>ImageWidth</Key>
<Value>300</Value>
</Meta>
<Meta>
<Key>ImageType</Key>
<Value>Logo</Value>
</Meta>
</Metas>
</Product>
<Product>
<Curated>false</Curated>
<Source>Games</Source>
<Title>State of Decay 2: Independence Pack</Title>
<Url>//www.microsoft.com/en-us/store/p/state-of-decay-2-independence-pack/9n0jhbm3618s</Url>
<ImageUrl>//store-images.s-microsoft.com/image/apps.19309.13920304356617547.62bf0ed6-7d21-4166-9bc0-99b6d7154bd1.e3af862c-7d10-4e9d-8f68-2c9a70d610b1?w=150&h=150</ImageUrl>
<Metas>
<Meta>
<Key>BigCatalogId</Key>
<Value>9N0JHBM3618S</Value>
</Meta>
<Meta>
<Key>ProductType</Key>
<Value>Durable</Value>
</Meta>
<Meta>
<Key>Icon</Key>
<Value>//store-images.s-microsoft.com/image/apps.19309.13920304356617547.62bf0ed6-7d21-4166-9bc0-99b6d7154bd1.e3af862c-7d10-4e9d-8f68-2c9a70d610b1</Value>
</Meta>
<Meta>
<Key>ImageHeight</Key>
<Value>1080</Value>
</Meta>
<Meta>
<Key>ImageWidth</Key>
<Value>1080</Value>
</Meta>
<Meta>
<Key>ImageType</Key>
<Value>BoxArt</Value>
</Meta>
</Metas>
</Product>
<Product>
<Curated>false</Curated>
<Source>Games</Source>
<Title>State Of Decay 2: Ultimate Edition</Title>
<Url>//www.microsoft.com/en-us/store/p/state-of-decay-2-ultimate-edition/9nsch45hz9hk</Url>
<ImageUrl>//store-images.s-microsoft.com/image/apps.50602.14365785075596216.2000000000013039869.e8c6dd03-ff3a-48fb-a8ad-479a95448240?w=150&h=150</ImageUrl>
<Metas>
<Meta>
<Key>BigCatalogId</Key>
<Value>9NSCH45HZ9HK</Value>
</Meta>
<Meta>
<Key>ProductType</Key>
<Value>Game</Value>
</Meta>
<Meta>
<Key>Icon</Key>
<Value>//store-images.s-microsoft.com/image/apps.50602.14365785075596216.2000000000013039869.e8c6dd03-ff3a-48fb-a8ad-479a95448240</Value>
</Meta>
<Meta>
<Key>ImageHeight</Key>
<Value>1080</Value>
</Meta>
<Meta>
<Key>ImageWidth</Key>
<Value>1080</Value>
</Meta>
<Meta>
<Key>ImageType</Key>
<Value>BoxArt</Value>
</Meta>
<Meta>
<Key>AppBgColor</Key>
<Value>#FFFFFF</Value>
</Meta>
</Metas>
</Product>
<Product>
<Curated>false</Curated>
<Source>Games</Source>
<Title>State of Decay 2: Doomsday Pack</Title>
<Url>//www.microsoft.com/en-us/store/p/state-of-decay-2-doomsday-pack/9pcqkkwf0zwp</Url>
<ImageUrl>//store-images.s-microsoft.com/image/apps.6519.14169313509850372.ade11659-c080-431a-9d6b-6933c4264efb.20f0ebab-bd4f-41c3-a514-7f9347266072?w=150&h=150</ImageUrl>
<Metas>
<Meta>
<Key>BigCatalogId</Key>
<Value>9PCQKKWF0ZWP</Value>
</Meta>
<Meta>
<Key>ProductType</Key>
<Value>Durable</Value>
</Meta>
<Meta>
<Key>Icon</Key>
<Value>//store-images.s-microsoft.com/image/apps.6519.14169313509850372.ade11659-c080-431a-9d6b-6933c4264efb.20f0ebab-bd4f-41c3-a514-7f9347266072</Value>
</Meta>
<Meta>
<Key>ImageHeight</Key>
<Value>1080</Value>
</Meta>
<Meta>
<Key>ImageWidth</Key>
<Value>1080</Value>
</Meta>
<Meta>
<Key>ImageType</Key>
<Value>BoxArt</Value>
</Meta>
</Metas>
</Product>
<Product>
<Curated>false</Curated>
<Source>Devices</Source>
<Title>State of Decay 2 for Xbox One</Title>
<Url>//www.microsoft.com/en-us/store/p/state-of-decay-2-for-xbox-one/8p2fgp3bf0fc</Url>
<ImageUrl>//img-prod-cms-rt-microsoft-com.akamaized.net/cms/api/am/imageFileData/RE1Tc21?ver=3d93&w=272&h=223&o=f&m=6&f=jpg</ImageUrl>
<Metas>
<Meta>
<Key>BigCatalogId</Key>
<Value>8P2FGP3BF0FC</Value>
</Meta>
<Meta>
<Key>ProductType</Key>
<Value>Devices</Value>
</Meta>
<Meta>
<Key>Icon</Key>
<Value>https://img-prod-cms-rt-microsoft-com.akamaized.net/cms/api/am/imageFileData/RE1Tc21?ver=3d93</Value>
</Meta>
<Meta>
<Key>ImageHeight</Key>
<Value>1540</Value>
</Meta>
<Meta>
<Key>ImageWidth</Key>
<Value>1189</Value>
</Meta>
<Meta>
<Key>ImageType</Key>
<Value>tile</Value>
</Meta>
</Metas>
</Product>
</Suggests>
</SuggestResults>
<SuggestResults>
<Source>microsoft-terms</Source>
<FromCache>false</FromCache>
<Type>term</Type>
<Suggests>
<Term>
<Curated>false</Curated>
<Txt>state of decay year one survival edition</Txt>
</Term>
<Term>
<Curated>false</Curated>
<Txt>state of decay year one survival edition for xbox one</Txt>
</Term>
<Term>
<Curated>false</Curated>
<Txt>state of decay for xbox 360 download code</Txt>
</Term>
</Suggests>
</SuggestResults>
</ResultSets>
<ErrorSets>
<SuggestErrorSet>
<Source>iris-products</Source>
<Message>Code: 2040. Message: Demand source returns error (Name: GN_ps, Error: No eligible content.).</Message>
</SuggestErrorSet>
</ErrorSets>
</SuggestResponse>
Sometimes happens that SuggestResults to be a single element instead of array.有时会发生 SuggestResults 是单个元素而不是数组。 So I created an
JsonProperty
as object and do trick in ParsedSuggestResult
property.所以我创建了一个
JsonProperty
作为对象并在ParsedSuggestResult
属性中做技巧。
I have the following class:我有以下课程:
public sealed class MsQueryXmlDetailResponse
{
public Suggestresponse SuggestResponse { get; set; }
public class Suggestresponse
{
public string xmlnsxsd { get; set; }
public string xmlnsxsi { get; set; }
public string Query { get; set; }
public Resultsets ResultSets { get; set; }
public Errorsets ErrorSets { get; set; }
}
public class Resultsets
{
[JsonProperty("SuggestResults")]
public object SuggestResultItems { get; set; }
public Suggestresult[] ParsedSuggestResult {
get
{
if(SuggestResultItems is Suggestresult)
{
return new Suggestresult[] { SuggestResultItems as Suggestresult };
}
var result = SuggestResultItems as Suggestresult[];
if(result != null)
{
return result;
}
return new Suggestresult[] { JsonConvert.DeserializeObject<Suggestresult>(SuggestResultItems.ToString()) };
}
}
}
public class Suggestresult
{
public string Source { get; set; }
public string FromCache { get; set; }
public string Type { get; set; }
public Suggests Suggests { get; set; }
}
public class Suggests
{
public Product[] Product { get; set; }
public Term[] Term { get; set; }
}
public class Product
{
public string Curated { get; set; }
public string Source { get; set; }
public string Title { get; set; }
public string Url { get; set; }
public string ImageUrl { get; set; }
public Metas Metas { get; set; }
}
public class Metas
{
public Meta[] Meta { get; set; }
}
public class Meta
{
public string Key { get; set; }
public string Value { get; set; }
}
public class Term
{
public string Curated { get; set; }
public string Txt { get; set; }
}
public class Errorsets
{
public Suggesterrorset SuggestErrorSet { get; set; }
}
public class Suggesterrorset
{
public string Source { get; set; }
public string Message { get; set; }
}
}
and I used Newtonsoft.Json to deserialize xml string format to a class (defined above):我使用 Newtonsoft.Json 将 xml 字符串格式反序列化为一个类(如上定义):
var xmldoc = new XmlDocument();
xmldoc.LoadXml(response);
var fromXml = JsonConvert.SerializeXmlNode(xmldoc);
MsQueryXmlDetailResponse data = JsonConvert.DeserializeObject<MsQueryXmlDetailResponse>(fromXml);
But I got:但我得到了:
Cannot deserialize the current JSON array into type because the type requires a JSON object (eg {"name":"value"}) to deserialize correctly.
无法将当前 JSON 数组反序列化为类型,因为该类型需要 JSON 对象(例如 {"name":"value"})才能正确反序列化。 To fix this error either change the JSON to a JSON object (eg {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (eg ICollection, IList) like List that can be deserialized from a JSON array.
要修复此错误,请将 JSON 更改为 JSON 对象(例如 {"name":"value"})或将反序列化类型更改为数组或实现集合接口的类型(例如 ICollection、IList),例如可以从 JSON 数组反序列化。 JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
JsonArrayAttribute 也可以添加到类型以强制它从 JSON 数组反序列化。
What should I do here ?我应该在这里做什么? If I do
SuggestResult[]
instead of object
and xml response contains one SuggestResult element then error occur again.如果我使用
SuggestResult[]
而不是object
并且 xml 响应包含一个 SuggestResult 元素,则错误再次发生。
The serializer doesn't know what to convert those objects to so by default, it will return objects deriving from JToken
.序列化程序不知道将这些对象转换为什么,因此默认情况下,它将返回从
JToken
派生的对象。 It knows nothing about the Suggesresult
type for the SuggestResults
property.它对
SuggestResults
属性的Suggesresult
类型SuggestResults
。
You need to annotate that property to give a hint to what to deserialize to.您需要注释该属性以提示要反序列化的内容。 But given that it can be one or more items, you will have to create a converter for it.
但考虑到它可以是一个或多个项目,您必须为它创建一个转换器。 Fortunately that should be simple to implement.
幸运的是,这应该很容易实现。
class SingleOrArrayJsonConverter<T> : JsonConverter
{
public override bool CanConvert(Type objectType) => objectType == typeof(List<T>);
public override bool CanRead => true;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var token = JToken.Load(reader);
switch (token.Type)
{
case JTokenType.Array:
return ToObject<List<T>>(token);
default:
return new List<T> { ToObject<T>(token) };
}
}
private TObj ToObject<TObj>(JToken token) => token.ToObject<TObj>();
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException();
}
Then you could just provide a more appropriate type on the object itself.然后,您可以在对象本身上提供更合适的类型。
public class Resultsets
{
[JsonProperty("SuggestResults")]
[JsonConverter(typeof(SingleOrArrayJsonConverter<Suggestresult>))]
public List<Suggestresult> SuggestResultItems { get; set; }
public Suggestresult[] ParsedSuggestResult => SuggestResultItems.ToArray();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.