【问题标题】:JSON Serialization in JSON.Net giving me Object when I need an Array当我需要一个数组时,JSON.Net 中的 JSON 序列化给了我对象
【发布时间】:2014-08-13 05:48:32
【问题描述】:

我正在尝试通过来自 ASP.Net 的 javascript 调用来填充 Highcharts 图表,我正在使用 JSON.Net 来序列化图表的数据。但是,我无法让从我的数据源创建的 JSON 与 Highcharts 似乎需要的格式相匹配。要查看问题,您只需检查 X 轴(类别),例如...

[{\"category\":\"August 15 and 16, 2014\"},{\"category\":\"March 21st, 2014\"},{\"category\":\"January 17 and 18, 2014\"},{\"category\":\"August 16 and 17, 2013\"},{\"category\":\"March 22nd, 2013\"},{\"category\":\"January 18 and 19, 2013\"},{\"category\":\"August 17 and 18, 2012\"},{\"category\":\"March 16th, 2012\"},{\"category\":\"January 20 and 21, 2012\"},{\"category\":\"August 19 and 20, 2011\"},{\"category\":\"January 21 and 22, 2011\"}]

应该是这样的……

['August 15 and 16, 2014', 'March 21st, 2014', 'January 17 and 18, 2014', 'August 16 and 17, 2013', 'March 22nd, 2013', 'January 18 and 19, 2013', 'August 17 and 18, 2012', 'March 16th, 2012', 'January 20 and 21, 2012', 'August 19 and 20, 2011', 'January 21 and 22, 2011']

所以基本上我的序列化是创建一个对象列表,我需要的只是一个值数组。为了解决这个问题,我需要生成一个值数组,或者让 Highcharts 构造函数读取对象。

ASP.Net 代码隐藏...

var tblNormal = Reporting.GetHistoricalTicketSalesReport();

    var queryX = from row in tblNormal.AsEnumerable()
        select new
        {
            category = row.ShowDateDescription
        };
    JObject o = JObject.FromObject(new
    {
        categories = queryX
    });
    string strXJSON = o.ToString();
    // value is: "{\"categories\":[{\"category\":\"August 15 and 16, 2014\"},{\"category\":\"March 21 and 21, 2014\"},{\"category\":\"January 17 and 18, 2014\"},{\"category\":\"August 16 and 17, 2013\"},{\"category\":\"March 22 and 22, 2013\"},{\"category\":\"January 18 and 19, 2013\"},{\"category\":\"August 17 and 18, 2012\"},{\"category\":\"March 16 and 16, 2012\"},{\"category\":\"January 20 and 21, 2012\"},{\"category\":\"August 19 and 20, 2011\"},{\"category\":\"January 21 and 22, 2011\"}]}"

    var queryY = from row in tblNormal.AsEnumerable()
        select new HighChartsPoint
        {
            y = row.TicketsSold
        };
    o = JObject.FromObject(new
    {
        series = queryY
    });
    string strYJSON = o.ToString();

    //This removes the wrapper around the inner JSON data
    strXJSON = F.AllAfter(strXJSON, ":").TrimEnd('}');
    //value is: "[{\"category\":\"August 15 and 16, 2014\"},{\"category\":\"March 21 and 21, 2014\"},{\"category\":\"January 17 and 18, 2014\"},{\"category\":\"August 16 and 17, 2013\"},{\"category\":\"March 22 and 22, 2013\"},{\"category\":\"January 18 and 19, 2013\"},{\"category\":\"August 17 and 18, 2012\"},{\"category\":\"March 16 and 16, 2012\"},{\"category\":\"January 20 and 21, 2012\"},{\"category\":\"August 19 and 20, 2011\"},{\"category\":\"January 21 and 22, 2011\"}]"
    strYJSON = F.AllAfter(strYJSON, ":").TrimEnd('}');

    //Call the function on the client browser
    ExecuteJavascript("InitShowChart(" + strXJSON + ", " + strYJSON + ");");

【问题讨论】:

  • 听起来您不应该使用 JSON 作为输入。你为什么不直接重写 ToString() 来返回你想要的,或者写一个方法来为你做呢?
  • 因为我试图在不编写自己的序列化库的情况下解决问题,不是因为我很懒(这会节省我的时间),而是因为 JSON 规范将来可能会发生变化,我'希望我所有的 JSON 都由一个能够自动跟上时代的库生成。
  • 我看到你的 json 格式不正确,因为不包含任何值的 y 参数。

标签: c# asp.net json highcharts json.net


【解决方案1】:

从你的json看来,你需要声明的类定义应该是这样的(见http://json2csharp.com/):

public class Title
{
    public string text { get; set; }
    public int x { get; set; }
}

public class Subtitle
{
    public string text { get; set; }
    public int x { get; set; }
}

public class XAxis
{
    public List<string> categories { get; set; }
}

public class PlotLine
{
    public int value { get; set; }
    public int width { get; set; }
    public string color { get; set; }
}

public class YAxis
{
    public Title title { get; set; }
    public List<PlotLine> plotLines { get; set; }
}

public class Tooltip
{
    public string valueSuffix { get; set; }
}

public class Legend
{
    public string layout { get; set; }
    public string align { get; set; }
    public string verticalAlign { get; set; }
    public int borderWidth { get; set; }
}

public class Series
{
    public string name { get; set; }
    public List<double?> data { get; set; }
}

public class HighChartsData
{
    public Title title { get; set; }
    public Subtitle subtitle { get; set; }
    public XAxis xAxis { get; set; }
    public YAxis yAxis { get; set; }
    public Tooltip tooltip { get; set; }
    public Legend legend { get; set; }
    public List<Series> series { get; set; }
}

如果你声明一个变量

var data = new HighChartsData();

填充其属性并序列化为

var json = JsonConvert.SerializeObject(data);

您的 json 将准备就绪。无需手动创建 json。

【讨论】:

  • 这不是简单地为具有内部结构的类创建一个 json 吗? (假设 HighChartsData 内部的内部类是上面的),哪个仍然不是他期望的输出?
  • @Noctis 我不明白你。用您认为正确的内容更新您的答案怎么样?
  • 据我了解,他只想使用值,而不使用“标题”或属性名称。 Json 显然将属性值名称与实际值配对,作为字符串。因此,如果您希望输入看起来像他要求的那样,那么它就不是真正的 JSON。但是,既然他解决了,那就无所谓了:)
【解决方案2】:

首先,您可以使用 NewtonSoft JSON。他很更新,经常维护他的图书馆。

其次,这是一个例子。让我们假设一个示例类:

public class AnExample{
    public int AnInt{get;set;}
    public string AString {get;set;}
    public DateTime ADate { get; set; }

    public override string ToString() {
        return "['" + AnInt + "','" + AString +"','"+ADate.ToString("s")+"']";
    }
}

你可以这样写:

void Main()
{
    var example = new AnExample() {
          AnInt = 1
        , AString = "Hello"
        , ADate = DateTime.Now
    };

    var examlpe_as_json = Newtonsoft.Json.JsonConvert.SerializeObject(example);
    // -> {"AnInt":1,"AString":"Hello","ADate":"2014-08-13T16:21:56.8348626+10:00"} 

    var input_to_highchart = example.ToString();
    // -> ['1','Hello','2014-08-13T16:21:56']       
}

当您需要稍后将字符串反序列化回类时,Json 很有用......但您想要的似乎是图表的输入。 我没有看到像上面的 ToString() 或辅助方法这样的方法。

如果您不关心订单(但我认为您会关心),您也可以利用一些反射来为您执行此操作,但这就是它开始变得更加......丑陋的地方...... :)

【讨论】:

    【解决方案3】:

    我无法从您的代码中准确判断,但您可能正在尝试序列化 List&lt;Category&gt;IEnumerable&lt;Category&gt; 或类似的东西。这就是你得到[{"category": "xxxxxx"}] 构造的原因。

    解决方案:首先将其转换为字符串数组:string[],然后序列化该数组。这应该会产生一个字符串数组,没有对象。

    【讨论】:

      【解决方案4】:

      这里的其他答案充满了好主意,有些甚至是更好的解决方法......但这是我提出的问题的基本解决方案。

      我改变了这个...

         var queryX = from row in tblNormal.AsEnumerable()
          select new
          {
              category = row.ShowDateDescription
          };
      

      到这里……

      var queryX = from row in tblNormal.AsEnumerable()
                       select row.ShowDateDescription;
      

      这解决了主要问题,显然由于我缺乏 LINQ 经验,我明确声明了一个对象集合。新版本仅序列化为值列表。

      用同样的方法,我也改变了这个....

      o = JObject.FromObject(new
      {
          series = queryY
      });
      string strYJSON = o.ToString();
      strYJSON = F.AllAfter(strYJSON, ":").TrimEnd('}');
      

      到这个....

      string strYJSON = JArray.FromObject(queryY).ToString(Newtonsoft.Json.Formatting.None);
      

      该更改消除了在序列化之后使用字符串操作的需要,因为我明确地序列化了一个数组而不是一个对象。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-11-30
        • 2013-08-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-04
        • 1970-01-01
        • 2017-04-10
        相关资源
        最近更新 更多