c# - 反序列化到 List<string> 字段时出现 "Unexpected character encountered while parsing value: [."异常

标签 c# json json.net jsonconvert

我有一个对象:

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);
    }
  }
}

我仍然遇到同样的错误。

最佳答案

您的问题是您的 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 中的字符串数组无法反序列化为构建类所需的单个字符串,因此您会看到所看到的异常。演示 fiddle #1 here .

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

  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] 标记它可能是私有(private)的或 protected .

    演示 fiddle #2 here .

  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
    }
    

    演示 fiddle #3 here .

  3. 将构造函数中的 text 参数重命名为不同的东西,比如 singletext,不太理想,因为 Json.NET 将传递 null 用于缺少的构造函数值,它最初将被添加到 Text 集合中并将保留在那里,除非该集合随后在反序列化过程中被替换。

    演示 fiddle #4 here .

相关阅读:

关于c# - 反序列化到 List<string> 字段时出现 "Unexpected character encountered while parsing value: [."异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63177674/

相关文章:

c# - 按名称动态获取/设置 C# 对象属性的最简单方法

c# - 类型 'T' 不可等待

java - 使用Gson解析Json数组和没有名字的对象

java - jsTree,刷新时需要展开所有节点

c# - 如何使用 Json.Net 和带有子类型的 Xamarin 反序列化 JSON?

c# - 通过 HTTPS 增量处理大型 XML 文件?

c# - 如何仅从 DateTime 数据类型获取时间

java - 文件无法正确读取

c# - 如何在 newtonsoft JSON 反序列化上接受单个属性的多个名称?

c# - 使用 Json.net 反序列化 JSON 对象数组