首页 > 解决方案 > “解析值时遇到意外字符:[。” 反序列化为列表时出现异常场地

问题描述

我有一个对象:

class Node
{
  public Node(string text)
  {
    Text = new List<string> { text };
  }

  public List<string> Text { get; set; }
}

当我尝试使用 Json.NET 将该对象的实例往返传输到 JSON 时,如下所示:

var root = new Node("");

var json = JsonConvert.SerializeObject(root);
root = JsonConvert.DeserializeObject<Node>(json);

我收到以下错误:

Unhandled Exception: Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: [. Path 'Text', line 2, position 11.
   at Newtonsoft.Json.JsonTextReader.ReadStringValue(ReadType readType)
   at Newtonsoft.Json.JsonTextReader.ReadAsString()
   at Newtonsoft.Json.JsonReader.ReadForType(JsonContract contract, Boolean hasConverter)

出于某种原因,它无法处理该List<string> Text领域,而我终其一生都无法弄清楚。

我实际上是在尝试反序列化它刚刚序列化的字符串。我可以尝试编写一个自定义转换器,但这里似乎没有必要。

有没有我可以用来帮助它的属性?

编辑:

创建了一个新的(.NET Framework 控制台应用程序)项目,其中只有一个Program.cs文件,其中包含以下代码:

using Newtonsoft.Json; // Version: 12.0.3
using System.Collections.Generic;

namespace ConsoleApp1
{
  class Node
  {
    public Node(string text)
    {
      Text = new List<string> { text };
    }

    public List<string> Text { get; set; }
  }

  class Program
  {
    static void Main()
    {
      var root = new Node("");

      var json = JsonConvert.SerializeObject(root);
      root = JsonConvert.DeserializeObject<Node>(json);
    }
  }
}

我仍然遇到同样的错误。

标签: c#jsonjson.netjsonconvert

解决方案


您的问题是您的Node类没有无参数构造函数。相反,它有一个参数化的构造函数。在这种情况下,Json.NET 将调用参数化构造函数,通过大小写不变的名称将构造函数参数与 JSON 属性匹配。不幸的是,text构造函数的参数与属性的类型不匹配Text。具体来说,参数是单个string,而属性是字符串数组:

class Node
{
    public Node(string text /* A single string named text */)
    {
        Text = new List<string> { text };
    }

    public List<string> Text { get; set; } // A collection of strings named Text
}

由于 JSON 中的字符串数组无法反序列化为构造类所需的单个字符串,因此您会看到您看到的异常。演示小提琴#1在这里

为了解决这个问题,您的选择包括:

  1. 添加无参数构造函数。Json.NET 默认会调用它:

    class Node
    {
        public Node() => Text = new List<string>();
    
        public Node(string text /* A single string named text */)
        {
            Text = new List<string> { text };
        }
    
        public List<string> Text { get; set; } // A collection of strings named Text
    }
    

    如果您用 标记它,它可能是私有的或受保护的[JsonConstructor]

    演示小提琴#2在这里

  2. 更改构造函数以接受字符串集合。 params string [] text似乎是最简单的:

    class Node
    {
        public Node(params string [] text)
        {
            Text = text.ToList();
        }
    
        public List<string> Text { get; set; } // A collection of strings named Text
    }
    

    演示小提琴#3在这里

  3. 将构造函数中的参数重命名为text不同的名称(例如singletext)并不理想,因为 Json.NET 将传递null缺少的构造函数值,该值最初将被添加到Text集合中,并将保留在那里,除非随后在反序列化期间替换集合。

    演示小提琴#4在这里

相关阅读:


推荐阅读