【问题标题】:Parsing json string that sometimes is an array解析有时是数组的json字符串
【发布时间】:2013-11-12 15:31:42
【问题描述】:

我正在尝试解析以下 json: http://libris.kb.se/xsearch?query=%22design%22+language:%28%22ENG%22%29&format=json&format_level=full&database=swepub 正如您在列表元素的第一项中看到的,描述是一个常规字符串。其他 8 个结果也是如此,但在第 9 个结果中,由于某种原因,它变成了一个字符串数组。

我正在使用 C# 和 DataContract 来尝试解析它,但它显然不起作用,因为结果之间的类型不同。 我该如何解决这个问题?我想可以手动解析所有内容,但我不想那样做。

这是我的 DataContract 的

[DataContract]
public class SwepubHeader
{
    [DataMember(Name = "xsearch")]
    public SwepubBody Body { get; set; }
}

[DataContract]
public class SwepubBody
{
    [DataMember(Name = "from")]
    public int From { get; set; }

    [DataMember(Name = "to")]
    public int To { get; set; }

    [DataMember(Name = "records")]
    public int Records { get; set; }

    [DataMember(Name = "list")]
    public SwepubSearchItem[] SearchItems { get; set; }
}

[DataContract]
public class SwepubSearchItem
{
    [DataMember(Name = "isbn")]
    public string ISBN { get; set; }

    [DataMember(Name = "title")]
    public string Title { get; set; }

    [DataMember(Name = "description")]
    public string Description { get; set; }

    [DataMember(Name = "identifier")]
    public string Identifier { get; set; }

    [DataMember(Name = "type")]
    public string Type { get; set; }

    [DataMember(Name = "publisher")]
    public string Publisher { get; set; }

    [DataMember(Name = "date")]
    public string Date { get; set; }

    [DataMember(Name = "language")]
    public string Language { get; set; }

    [DataMember(Name = "relation")]
    public string Relation { get; set; }

    [DataMember(Name = "subject")]
    public string[] Subjects { get; set; }

    [DataMember(Name = "creator")]
    public string[] Creators { get; set; }
}

这就是我解析它的方式

                    using (var response = request.GetResponse() as HttpWebResponse)
                {
                    if (response != null)
                    {
                        if (response.StatusCode != HttpStatusCode.OK)
                            throw new Exception(String.Format(
                                "Server error (HTTP {0}: {1}).",
                                response.StatusCode,
                                response.StatusDescription));
                        var jsonSerializer = new DataContractJsonSerializer(typeof(SwepubHeader));
                        object objResponse = jsonSerializer.ReadObject(response.GetResponseStream());
                        var jsonResponse = objResponse as SwepubHeader;
                        return jsonResponse;
                    }
                }

【问题讨论】:

  • 如果他们给你不同的数据类型,那么他们做错了什么,你应该告诉他们。他们应该为他们的记录提供一致的类型。为了在不手动解析的情况下绕过它,您可以只定义两种相似的类型(都从相同的基数派生) - 一种带有字符串,一种带有字符串数组 - 您可以尝试/捕获序列化到一个然后另一个.这两个类都可以实现类似GetDescription() 的东西,它读取字符串或连接字符串数组。
  • 可能会有所帮助:stackoverflow.com/questions/7501846/…
  • 我会使用 Json.Net 而不是 DataContractJsonSerializer 。它的反序列化速度几乎是原来的两倍,并且具有更多功能。例如,您可以创建一个 JsonConverter 来获取该值并让您确定它是如何反序列化的。

标签: c# json parsing datacontract


【解决方案1】:

这对于他们的 JSON 格式来说确实不是一个很好的设计,但你可以通过将描述作为一个对象来处理它。然后,如何处理该对象取决于您,但您可以创建另一个属性将其转换为您需要的对象:

[DataMember(Name = "description"]
private object _description;

public string Description
{
    get
    {
        if (_description != null)
        {
            if (_description is string)
            {
                // Do Nothing
                // You can remove this, just putting this here to 
                //   show conditional is implicit
            }
            else if (_description is string[])
            {
                // Join string[] using '\n\n' as the connector
                _description = string.Join("\n\n", (string[])_description);
            }
        }

        return _description as string;
    }
}

【讨论】:

  • 我同意,这是一个糟糕的设计,但它不是我的,我不能让他们改变它。谢谢你的回答,没想到把它变成一个对象!
【解决方案2】:

url 返回两个不同的 JSON 对象。这对他们来说确实不是一个很好的设计,但如果你无法控制它,那么一个选择是尝试使用字符串数据对其进行反序列化,如果失败则使用字符串数组对其进行反序列化。

编辑:为了轻松完成这项工作,您应该将描述反序列化为对象。但是它不是字符串数组...它是字符串或对象数组...所以下面的代码将处理这个...用以下内容替换您的 Description 属性...

[DataMember(Name = "description")]
public object description { get; set; }

public string Description {
    get
    {
        var seperator = string.Empty; // replace with what you want
        var s = description as string;
        if (s != null)
            return s;
        var sArray = description as object[];
        if (sArray != null)
            return String.Join(seperator, sArray);
        return null;
    }
    set
    {
        description = value;
    }
}

【讨论】:

  • 谢谢,没想过把类型变成对象!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-12
  • 1970-01-01
  • 1970-01-01
  • 2022-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多