gpt4 book ai didi

c# - Newtonsoft.Json 解析不正确的json

转载 作者:太空狗 更新时间:2023-10-29 23:12:59 25 4
gpt4 key购买 nike

我遇到了一个奇怪的问题:给定这样的字符串 {"text":"s","cursorPosition":189,"dataSource":"json_northwind", 这不是一个正确的 json,它仍然被成功解析。

这是类:

public class CompletionDataRequest
{
public CompletionDataRequest(string text, int cursorPosition, string dataSource, string project)
{
Text = text;
CursorPosition = cursorPosition;
DataSource = dataSource;
Project = project;
}

public string Text { get; }
public int CursorPosition { get; }
public string DataSource { get; }
public string Project { get; }
}

这是一个意外成功的测试:

var s = @"{""text"":""s"",""cursorPosition"":189,""dataSource"":""json_northwind"",";
var request = JsonConvert.DeserializeObject<CompletionDataRequest>(s);
request.Text.Should().Be("s");
request.CursorPosition.Should().Be(189);
request.DataSource.Should().Be("json_northwind");
request.Project.Should().BeNull();

库是否有一些松散的解析规则或者这可能是一个错误?我是库版本9.0.1

最佳答案

更新

一个问题 Deserializing unclosed object succeeds when the object has a parameterized constructor. #1038为这个问题打开了。它已在 Json.NET release 10.0.1 中修复在变更集中0721bd4 .

原始答案

您在 Json.NET 中发现了一个错误。只有当您的对象是使用参数化构造函数构造时才会出现。如果我将您的对象修改为具有非参数化构造函数:

public class CompletionDataRequest
{
public CompletionDataRequest(string text, int cursorPosition, string dataSource, string project)
{
Text = text;
CursorPosition = cursorPosition;
DataSource = dataSource;
Project = project;
}

[JsonConstructor]
private CompletionDataRequest()
{
}

[JsonProperty]
public string Text { get; private set; }
[JsonProperty]
public int CursorPosition { get; private set; }
[JsonProperty]
public string DataSource { get; private set; }
[JsonProperty]
public string Project { get; private set; }
}

然后 Json.NET 将正确抛出一个 JsonSerializationException

错误原因如下。使用无参数构造函数创建对象时,Json.NET 首先构造对象,然后用 JsonSerializerInternalReader.PopulateObject() 填充它。 .此方法具有以下(简化的)逻辑:

    private object PopulateObject(object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, string id)
{
bool finished = false;
do
{
switch (reader.TokenType)
{
case JsonToken.PropertyName:
{
// Read and process the property.
}
case JsonToken.EndObject:
finished = true;
break;
case JsonToken.Comment:
// ignore
break;
default:
throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType);
}
} while (!finished && reader.Read());

if (!finished)
{
ThrowUnexpectedEndException(reader, contract, newObject, "Unexpected end when deserializing object.");
}

return newObject;
}

如您所见,有逻辑 if (!finished) 来验证对象是否实际关闭。

但是,当使用参数化构造函数创建对象时,会在构造对象之前读取属性,使用 JsonSerializerInternalReader.ResolvePropertyAndCreatorValues() :

    private List<CreatorPropertyContext> ResolvePropertyAndCreatorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType)
{
List<CreatorPropertyContext> propertyValues = new List<CreatorPropertyContext>();
bool exit = false;
do
{
switch (reader.TokenType)
{
case JsonToken.PropertyName:
// Read and process the property.
break;
case JsonToken.Comment:
break;
case JsonToken.EndObject:
exit = true;
break;
default:
throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType);
}
} while (!exit && reader.Read());

return propertyValues;
}

如您所见,没有等效的检查 exit 是否为真。

一个问题 Deserializing unclosed object succeeds when the object has a parameterized constructor. #1038为此而开放。

关于c# - Newtonsoft.Json 解析不正确的json,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39943346/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com