【问题标题】:posting single item in json array to .net object将 json 数组中的单个项目发布到 .net 对象
【发布时间】:2012-12-21 08:56:51
【问题描述】:

我在 .net 中有一个对象,主要用于接收一些 json。 它通常工作得很好,但是当数字数组中有单个项目时,json 库会将其转换为单个数字,而不是具有单个项目的数组。 .net 将此作为错误抛出,因为它是单个 int32 而不是 int32s 数组 我尝试转换为 json.net 但这并不奇怪同样的错误

据我所知,没有办法在我的对象中有替代定义,是吗?

下面是我的对象的定义

public class EnquiryModel
{
    public string Name;
    public string Email;
    public string Phone;
    public string JobCode;
    public string Message;
    public int ReferralSource;
    public Dictionary<string, int> PickList;
    public int[] Studios;
    public int[] Services;
    public string[] BookingEnquiries;
}

这是我用来填充它的代码

using Newtonsoft.Json;
EnquiryModel enq = JsonConvert.DeserializeObject<EnquiryModel>(json);

以前我用过

using System.Web.Script.Serialization;
JavaScriptSerializer j = new JavaScriptSerializer();
EnquiryModel enq = j.Deserialize<EnquiryModel>(json);

它们都产生相同的错误

不确定避免此问题的最佳方法是什么

当它在客户端被序列化时,具有单个项目的数组被转换为单个数字 不知道为什么会这样:)?

已解决

标记为以下解决方案的答案非常有效 - 谢谢 :)

我必须做出一些我认为值得分享的微小更改

首先我发现它是作为 Int64 传递的,所以我的检查是针对两种带 or 的类型

我也有一些代码使用了这个对象,因为公共变量不再是一个数组而是一个对象,所以我必须在用法中添加一个强制转换:

foreach (int studio in enq.Studios)

不得不改成

foreach (int studio in (Int32[])enq.Studios)

这是该对象的完整来源 如果有某种方法可以概括重复的代码以使其更易于阅读,那就太好了 但这很可能是镀金的:)

public class EnquiryModel
{
    public string Name;
    public string Email;
    public string Phone;
    public string JobCode;
    public string Message;
    public int ReferralSource;
    public Dictionary<string, int> PickList;
    //allow the arrays of 1 to many values to be submitted as a single value
    // instead of a single item in an array
    private string[] bookingEnquiries;
    public object BookingEnquiries
    {
        get { return bookingEnquiries; }
        set
        {
            if (value.GetType() == typeof(string))
            {
                bookingEnquiries = new string[] { (string)value };
            }
            else if (value.GetType() == typeof(string[]))
            {
                bookingEnquiries = (string[])value;
            }
        }
    }
    private int[] studios;
    public object Studios
    {
        get { return studios; }
        set
        {
            if (value.GetType() == typeof(Int32) || value.GetType() == typeof(Int64))
            {
                studios = new Int32[] { (Int32)value };
            }
            else if (value.GetType() == typeof(Int32[]))
            {
                studios = (Int32[])value;
            }
        }
    }
    private int[] services;
    public object Services
    {
        get { return services; }
        set
        {
            if (value.GetType() == typeof(Int32) || value.GetType() == typeof(Int64))
            {
                services = new Int32[] { (Int32)value };
            }
            else if (value.GetType() == typeof(Int32[]))
            {
                services = (Int32[])value;
            }
        }
    }

}

【问题讨论】:

  • 向我们展示您是如何构建 json 对象的。这就是最有可能出现问题的地方。
  • 是的,如果 json 不是那样生成肯定会更好,但显然这是有效的 - 所以我必须接受这一点,我可以看到允许这样做是很合乎逻辑的,它也是超出我的控制范围
  • 我不认为问题与您如何反序列化有关 - 我认为问题出在 json 本身,一旦它到达您的反序列化器。例如,它给你一个 int,而不是一个有一个 int 的数组。
  • 序列化超出了我的控制范围,在另一个组织的另一个开发人员手中,他告诉我,如果提交了一个包含单个项目的数组,他使用的 json 会自动进行这种“更正”,它会转换这到一个数字。我已经看过源代码并且看到图书馆正在这样做并且可以复制它。我可以坚持 json 以预期的格式出现并在客户端强制进行更改,但如果这是一个真正的问题,那么感觉好的解决方案是也接受这个有效的输入。

标签: c# .net json


【解决方案1】:

我会让变量 p[rivate 并通过 getter 和 setter 公开它们。在 setter 中,您可以评估传入的属性并进行适当的设置。

    private Int32[] numbers;

    public object Numbers
    {
        get { return numbers; }
        set
        {
            if (value.GetType() == typeof(Int32))
            {
                numbers = new Int32[] { (Int32)value };
            }
            else if (value.GetType() == typeof(Int32[]))
            {
                numbers = (Int32[])value;
            }
        }
    }

【讨论】:

  • 这看起来像是一个合乎逻辑的解释......谢谢你在这种情况下设置它的代码是否保持不变,即 EnquiryModel enq = JsonConvert.DeserializeObject(json);
  • 应该,因为该方法应该只是分配给属性。如果这有帮助,记得标记为答案。
  • 是的,我非常喜欢这个解决方案,它很优雅,感觉不错 - 我明天会试试 - 并将标记为答案
  • 不,这实际上不起作用,因为 typeof() 在发送数组时是 object[],不会强制转换为 int[]
  • 奇数。对我来说效果很好。
【解决方案2】:

我觉得你需要编写自己的包装器来检查是否存在T 类型的单个项目,它将其转换为new T[]{item}。您可以使用 JSON.NET 的 JObject 类。

JObject o = JObject.Parse(response);

并针对您正在寻找的特定属性评估 o

【讨论】:

  • 我曾考虑过这一点,我只是想知道是否有更好的方法来做到这一点,如果有一种方法可以使用替代构造函数,则不会产生大量需要维护的额外代码,一个可以以某种方式采用替代类型的初始化器的设置器,感觉像是正确的解决方案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-19
  • 1970-01-01
  • 2014-11-25
  • 1970-01-01
  • 2011-01-10
  • 2017-10-31
相关资源
最近更新 更多