C# 当响应为xml时,无法从将当前JSON数组反序列化为类型

C# 当响应为xml时,无法从将当前JSON数组反序列化为类型,c#,arrays,xml,C#,Arrays,Xml,我从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>

我从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&amp;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&amp;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&amp;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&amp;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&amp;w=272&amp;h=223&amp;o=f&amp;m=6&amp;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>
我使用Newtonsoft.Json将xml字符串格式反序列化为一个类(定义见上文):

var xmldoc=new XmlDocument();
LoadXml(响应);
var fromXml=JsonConvert.SerializeXmlNode(xmldoc);
MsQueryXmlDetailResponse data=JsonConvert.DeserializeObject(fromXml);
但我得到了:

无法将当前JSON数组反序列化为类型,因为类型 需要一个JSON对象(例如{“name”:“value”})来反序列化 正确地要修复此错误,请将JSON更改为JSON对象 (例如{“name”:“value”})或将反序列化类型更改为数组或 实现集合接口的类型(例如ICollection、, IList)类似于可以从JSON数组反序列化的列表。 还可以将JsonArrayAttribute添加到类型中,以强制它 从JSON数组反序列化


我在这里该怎么办?如果我使用
SuggestResult[]
而不是
object
,并且xml响应包含一个SuggestResult元素,则再次发生错误。

序列化程序不知道将这些对象转换成什么,因此默认情况下,它将返回从
JToken
派生的对象。它不知道
suggestresult
属性的
suggestresult
类型

您需要对该属性进行注释,以提示要反序列化的内容。但考虑到它可以是一个或多个项目,您必须为它创建一个转换器。幸运的是,这应该很容易实现

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();
}
class SingleOrrayJSONConverter:JsonConverter
{
公共覆盖布尔CanConvert(类型objectType)=>objectType==typeof(列表);
public override bool CanRead=>true;
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
var token=JToken.Load(读卡器);
开关(token.Type)
{
案例JTokenType.Array:
返回到对象(令牌);
违约:
返回新列表{ToObject(token)};
}
}
私有TObj-tobject(JToken-token)=>token.tobject();
公共覆盖boolcanwrite=>false;
public override void WriteJson(JsonWriter writer,object value,JsonSerializer serializer)=>throw new NotImplementedException();
}
然后您可以在对象本身上提供一个更合适的类型

public class Resultsets
{
    [JsonProperty("SuggestResults")]
    [JsonConverter(typeof(SingleOrArrayJsonConverter<Suggestresult>))]
    public List<Suggestresult> SuggestResultItems { get; set; }

    public Suggestresult[] ParsedSuggestResult => SuggestResultItems.ToArray();
}
公共类结果集
{
[JsonProperty(“SuggestResults”)]
[JsonConverter(类型(SingleOrrayJSONConverter))]
公共列表SuggestResultItems{get;set;}
public Suggestresult[]ParsedSuggestResult=>SuggestResultItems.ToArray();
}

您可以做的第一件事是检查
fromXml
中的JSON字符串,找出它与您的对象模型不一致的地方…与其从XML转换为JSON并使用JSON反序列化,为什么不直接将XML反序列化到您的类实例中呢?如果我得到SuggestResult数组,会发生什么?如果我得到SuggestResult的一个元素,会发生什么?将被视为包含一个元素的数组?如果使用包含一个SuggestResult的XML为代码提供数据,为什么不试试看会发生什么情况?我得到了
这是不应该的。。。
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();
}
public class Resultsets
{
    [JsonProperty("SuggestResults")]
    [JsonConverter(typeof(SingleOrArrayJsonConverter<Suggestresult>))]
    public List<Suggestresult> SuggestResultItems { get; set; }

    public Suggestresult[] ParsedSuggestResult => SuggestResultItems.ToArray();
}