【问题标题】:Trying to deserialize json array试图反序列化 json 数组
【发布时间】:2018-03-27 19:43:47
【问题描述】:

我正在尝试反序列化我项目中的一个本地文件,该文件是一个 json 文件。但是我在当前代码中遇到了这个错误:

"解析值时遇到意外字符:G.Path '', line 0, position 0"

C#代码

string filepath = Application.StartupPath + @"\city.list.json";
for(int i = 0; i< 40; i++)
{
    foreach (string x in File.ReadLines(filepath))
    {
        if(x.Contains("id") || x.Contains("name"))
        {
            var data = JsonConvert.DeserializeObject<City.values>(filepath);
            //City city = JsonConvert.DeserializeObject<City>(File.ReadAllText(filepath));
            //cityList.Add(data.name, data.id);
        }
        else
        {

        }
    }
}

class City
{
    [JsonObject(MemberSerialization = MemberSerialization.OptIn)]
    public class values
    {
        [JsonProperty(PropertyName = "id")]
        public string id { get; set; }

        [JsonProperty(PropertyName = "name")]
        public string name { get; set; }
    }
}

我试图反序列化的 Json 文件。这只是从文件中提取的一个快速示例。挺大的^^

[
   {
      "id":707860,
      "name":"Hurzuf",
      "country":"UA",
      "coord":{
         "lon":34.283333,
         "lat":44.549999
      }
   },
   {
      "id":519188,
      "name":"Novinki",
      "country":"RU",
      "coord":{
         "lon":37.666668,
         "lat":55.683334
      }
   },

【问题讨论】:

  • 你需要一个包含 City 数组的类,但你目前没有
  • 这里出了点问题,为什么要逐行读取文件却反序列化filePath?您应该将所有文本读入一个字符串并反序列化,不需要循环。
  • 感谢 Ron 的优化建议:D,嗯,文件有 180 万行长,所以我只是想获取文件中的前 40 行,这就是我做 for 循环的原因。我还能按照你的方式做,只是让前 40 行没有循环吗?
  • 否,因为从 JSON 文件中随机抽取“块”不是有效的 JSON,所以会缺少右括号。
  • 你明白吗,你在循环中读取文件 40 次,然后对于每个字符串,你想反序列化该字符串(json 的一部分),而是反序列化文件的路径......?

标签: c# json serialization


【解决方案1】:

您似乎对 JSON 反序列化的工作原理有一些巨大的误解。首先要解决的是您不应该遍历 json 文件的行。正如 cmets 中所指出的,您的 JSON 文件非常大(约 180 万行),因此最好的办法是使用 DeserializeObject()JsonReader 重载,请参阅 Json.NET performance tips

List<City.values> cities = new List<City.values>();
string filepath = Application.StartupPath + @"\city.list.json";
using (StreamReader sr = new StreamReader(filepath))
using (JsonReader reader = new JsonTextReader(sr))
{
    JsonSerializer serializer = new JsonSerializer();
    // read the json from a stream
    // json size doesn't matter because only a small piece is read at a time from the HTTP request
    cities = JsonConvert.DeserializeObject<List<City.values>>(reader);
}

请注意这一行:

cities = JsonConvert.DeserializeObject<List<City.values>>(reader);

这里我们利用 JSON.NET 进行反序列化。您的代码和我在这里包含的代码之间的区别在于您的 JSON 是对象的 collection,这意味着您需要反序列化为 @987654328 的 collection @objects,在这种情况下我使用了List&lt;T&gt;

现在我们有了一个变量 cities,它是您的 JSON 中包含的 City.values 对象的集合。

【讨论】:

  • 如果文件很长(实际上是 180 万行),我不会这样做。我会直接流式传输。请参阅 newtonsoft.com/json/help/html/Performance.htm#MemoryUsageCan Json.NET serialize / deserialize to / from a stream?
  • @dbc 好电话,我认为 OP 最初使用的是 RealAllLines()(实际上与 ReadAllText 相同)。我在问题中添加了关于性能的注释
  • 谢谢,非常感谢您的回答。然而。我只对反序列化文件中的“id”和“name”行感兴趣。我之前有这个解决方案,但我发现无法反序列化我想要的特定行。
  • @HelpIsNeeded - 只需从 c# 数据模型中省略您不想要的属性,序列化程序就会在从文件流反序列化时跳过它们。
  • @HelpIsNeeded 你的类可以是那些属性。你不必有一个匹配整个对象的 POCO
猜你喜欢
  • 2015-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-23
  • 1970-01-01
  • 2012-01-24
  • 2017-01-18
相关资源
最近更新 更多