Newtonsoft.JSON - 为什么在反序列化字符串化 JSON 模式期间出现错误

问题描述 投票:0回答:2

我正在从客户端接收代表 ChatGPT API 请求中的函数的数据,可在此处查看:https://platform.openai.com/docs/api-reference/chat/create

我希望接收到的 JSON 由 Newtonsoft.Json 进行解析,然后在 JSON 解析期间进行 JSchema 解析,但似乎 JSchema 解析可能发生在正常的 JSON 解析之前,并且我的

[JsonIgnore]
具有讽刺意味的是,属性被 JSchema 解析忽略。

这是我的主要问题:

  • 为什么在下面的 for 循环中处理
    json1
    会导致错误?
  • ParametersJson
    的类型是字符串时,为什么 JSchema 解析器需要一个对象或布尔值?
  • 是否没有一种实用的方法可以像我在
    json1
    中那样对 JSON 进行编码,并按照我期望的方式将其全部反序列化,而不会出现错误?我想在客户端将 JSON 模式保留为字符串。

这是错误:

未处理的异常。 Newtonsoft.Json.Schema.JSchemaReaderException:读取架构时遇到意外标记。预期 StartObject,布尔值,得到字符串。路径“参数”,第 7 行,位置 9。 在 Newtonsoft.Json.Schema.Infrastruct.JSchemaReader.EnsureToken(JsonReader reader,字符串名称,List`1 tokenTypes,字符串 errorMessage)

这是 .NET Fiddle:https://dotnetfiddle.net/GE8OMP

using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Schema;

public class Program
{
    public static void Main()
    {
        string json0 = @"
{
    'Name': 'TestFunction',
    'Description': 'This is a test function.',
    'parameters': 
    {
        'type': 'object', 
        'properties': 
        {
            'prop1': 
            {
                'type': 'string'
            }
        }
    }
}".Replace("'", "\"");
        string json1 = @"
{
    'Name': 'TestFunction',
    'Description': 'This is a test function.',
    'parameters': 
    '{
        'type': 'object', 
        'properties': 
        {
            'prop1': 
            {
                'type': 'string'
            }
        }
    }'
}".Replace("'", "\"");
        var arr = new[]{json0, json1};
        foreach (var json in arr)
        {
            Function deserializedFunction = JsonConvert.DeserializeObject<Function>(json);
            Console.WriteLine($"Name: {deserializedFunction.Name}");
            Console.WriteLine($"Description: {deserializedFunction.Description}");
            Console.WriteLine($"Parameters: {deserializedFunction.Parameters}");
            Console.WriteLine("-------------");
        }
    }
}

#nullable enable
public class Function
{
    /// <summary>
    /// The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64.
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// A description of what the function does, used by the model to choose when and how to call the function.
    /// </summary>
    public string? Description { get; set; }

    /// <summary>
    /// The parameters the functions accepts, described as a JSON Schema object.
    /// <br></br>
    /// <br></br>
    /// To describe a function that accepts no parameters, provide the value {"type": "object", "properties": { } }.
    /// </summary>
     // Need to convert from string coming from client to the JSchema object.
    [JsonIgnore]
    public JSchema Parameters { get; set; }

    [JsonProperty("parameters")]
    public string ParametersJson { get => Parameters.ToString(); set => Parameters = JSchema.Parse(value); }

    public Function(string name, string? description, JSchema parameters)
    {
        Name = name;
        Description = description;
        Parameters = parameters;
    }
}
c# json json.net jsonschema json-deserialization
2个回答
1
投票

第一件事是你的第二个 JSON 无效:

  1. parameters
    值中的引号需要转义(
    \"
    )。

  2. JSON 中字符串值不能有多行。

正确的 JSON 应该是:

{
    "Name": "TestFunction",
    "Description": "This is a test function.",
    "parameters": "{\"type\": \"object\", \"properties\": {\"prop1\": {\"type\": \"string\"}}}"
}

假设您已经修复了 JSON 问题,对于构造函数,您应该处理具有多种类型的

parameters

  1. 在构造函数中将

    parameters
    类型更改为
    JToken
    ,以允许值有多种类型。

  2. 处理不同

    parameters.Type
    JTokenType
    String
    Object
    )。

public Function(string name, string? description, JToken parameters)
{
    Name = name;
    Description = description;
        
    if (parameters.Type == JTokenType.String)
    {
        Parameters = JSchema.Parse(parameters.ToString());
    }
    else if (parameters.Type == JTokenType.Object)
    {
        Parameters = parameters.ToObject<JSchema>();
    }
}

注意处理不同

if-else
JTokenType
语句也可以简化为:

Parameters = JSchema.Parse(parameters.ToString());

1
投票

恕我直言,你需要修复 json1

    string json1 = @"
{
    'Name': 'TestFunction',
    'Description': 'This is a test function.',
    'parameters': 
    '{
        'type': 'object', 
        'properties': 
        {
            'prop1': 
            {
                'type': 'string'
            }
        }
    }'
}".Replace("'{", "{").Replace("}'", "}").Replace("'", "\"");
© www.soinside.com 2019 - 2024. All rights reserved.