【问题标题】:Deserialize Json String Type Not known反序列化 Json 字符串类型未知
【发布时间】:2016-07-25 10:01:49
【问题描述】:

我有如下 JSON:

   {
 "request" :
 {
  "command" : "series",
  "series_id" : "PET.WCRSTUS1.W"
 },
 "series" : [
  {
   "series_id" : "PET.WCRSTUS1.W",
   "name" : "U.S. Ending Stocks of Crude Oil, Weekly",
   "units" : "Thousand Barrels",
   "f" : "W",
   "unitsshort" : "Mbbl",
   "description" : "U.S. Ending Stocks of Crude Oil",
   "copyright" : "None",
   "source" : "EIA, U.S. Energy Information Administration",
   "iso3166" : "USA",
   "geography" : "USA",
   "start" : "19820820",
   "end" : "20160715",
   "updated" : "2016-07-20T13:18:37-0400",
   "data" : [["20160715", 1214561], 
   ["20160708", 1216904], 
   ["20160701", 1219452], 
   ["20160624", 1221677], 
   ["20160617", 1225730], 
   ["20160610", 1226647], 
   ["20160603", 1227580]]
  }
 ]
}

我使用在线 JSON 转换器生成 C#,如下所示:

public class Request
{
    public string command { get; set; }
    public string series_id { get; set; }
}

public class Series
{
    public string series_id { get; set; }
    public string name { get; set; }
    public string units { get; set; }
    public string f { get; set; }
    public string unitsshort { get; set; }
    public string description { get; set; }
    public string copyright { get; set; }
    public string source { get; set; }
    public string iso3166 { get; set; }
    public string geography { get; set; }
    public string start { get; set; }
    public string end { get; set; }
    public string updated { get; set; }
    public List<List<Object>> data { get; set; }
}


public class RootObject
{
    public Request request { get; set; }
    public List<Series> series { get; set; }
}

现在,请注意“系列”的“数据”属性是一个列表列表。我想做的是创建一个类来表示这些:

public class DataItem
{
    public string Date { get; set; }
    public int Value { get; set; }
}

然后修改Series类如下:

public class Series
{
    public string series_id { get; set; }
    public string name { get; set; }
    public string units { get; set; }
    public string f { get; set; }
    public string unitsshort { get; set; }
    public string description { get; set; }
    public string copyright { get; set; }
    public string source { get; set; }
    public string iso3166 { get; set; }
    public string geography { get; set; }
    public string start { get; set; }
    public string end { get; set; }
    public string updated { get; set; }
    public List<DataItem> data { get; set; }
}

当我这样做时,我在 data 属性中获得了正确数量的项目,但每个单独的 DataItem 都有默认值(空字符串和值 0)。请有人建议如何(如果)实现这一点。

我的反序列化使用 System.Runtime.Serialization(不是 Json.Net)。为此目的,反序列化例程可以被认为是我无法控制的。不确定这是否相关,但下面是 sn-p:

    public static T FromJsonString<T>(string json, Type[] extraTypes = null)
    {
        T result;
        var serializer = new DataContractJsonSerializer(typeof(T), extraTypes ?? new Type[] { });

        using (var stream = new MemoryStream())
        {
            using (var writer = new StreamWriter(stream))
            {
                writer.Write(json);
                writer.Flush();
                stream.Position = 0;
                result = (T) serializer.ReadObject(stream);
            }
        }

        return result;
    }

总结一下:

  • 如何获取要反序列化到我的 DataItem 类的数据对象列表? JSON 中没有表示类型

我正在使用 .Net 4.0。

希望这很清楚 - 如果没有,请发表评论。

【问题讨论】:

  • 你能改变json吗?如果不更改 json,我认为您想要的是不可能的。
  • JSON 通过外部服务返回。我想我可以在反序列化之前操作字符串,但它是一个巨大的字符串(有数千个 DataItem,为了清楚起见我已经缩短了示例)。简短的回答 - 不是真的!我曾希望有一种方法可以通过 Series 类的属性。
  • 我不会操纵字符串 - 你会自找麻烦!看我的回答

标签: c# .net json serialization


【解决方案1】:

如果无法更改传入的 json,我认为您必须同时拥有这两个属性:

public List<List<Object>> Data { get; set; }
public List<DataItem> DataMapped { get; set; }

反序列化为您的“数据”属性,然后具有一个映射函数,该函数将从data 映射到dataMapped

例如

//deserialize here, then...
for (int i = 0; i < Data.Count; i++)
{
    DataMapped.Add(new DataItem() { Date = Data[i][0].ToString(), Value = int.Parse(Data[i][1].ToString()) });
}

这里没有检查预期值,因此您可能需要添加它 - 例如内部列表肯定包含 2 个对象等...

【讨论】:

  • 谢谢@Rick。我会赞成但不接受您的回答(我仍然希望有一种基于属性的方法来实现这一点!)。我不想再次遍历所有数据。
  • 不用担心 - 是的,可能有,但如果有的话,我就无法做到 - 我也有兴趣看到。
  • 你总是可以让你的 DataTem 有一个List&lt;Object&gt; Stuff 属性,然后让你的 Date 和 Value 属性返回 Stuff[0] 和 Stuff[1]。我已经更新了我的答案以展示这种方法
  • 啊 - 是的,我猜数据类型不会正确匹配!值得一试
【解决方案2】:

如果你特别看 json

     "data" : [["20160715", 1214561], 
   ["20160708", 1216904], 
   ["20160701", 1219452], 
   ["20160624", 1221677], 
   ["20160617", 1225730], 
   ["20160610", 1226647], 
   ["20160603", 1227580]]

Data是一个Array of Arrays,所以你使用的在线生成器已经正确地将json转换为public List&lt;List&lt;Object&gt;&gt; data { get; set; }

但是,您稍后可以通过简单地迭代 public List&lt;List&lt;Object&gt;&gt; data { get; set; } 并为每个内部列表创建一个 DataItem 来将其映射到 public List&lt;DataItem&gt; data { get; set; }

【讨论】:

  • 谢谢@PreetSingh。我知道这一点,但希望将其作为反序列化的一部分,假设反序列化器必须已经在迭代。
  • 正如您所说,您的序列化程序超出范围,因此正在修改 FromJsonString 方法,没有太多剩余可以插入自定义序列化程序,但是如果您的应用程序是,您可以插入 MediaTypeFormatter一个 Web API 应用程序。但我的观点是,如果传入的数据是一个数组数组,那么为什么要在一天结束时转换对象数组 DataItem 也是一个数据,在这种情况下是元组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多