.net 如何将配置从JSON文件绑定到C#中的示例?

4ioopgfo  于 2023-08-08  发布在  .NET
关注(0)|答案(3)|浏览(106)

我想将JSON文件中的配置绑定到**HttpApiClientOptions的示例。但是,绑定Body属性时遇到了一些问题。定义为Dictionary<string, object>?后,Body属性正确包含modeltemperature键值对,但messages的值为空,无法从中检索{"role":"user", "content":"hello!"}**。
C#代码:

var config = new ConfigurationBuilder()
    .AddJsonFile(configFilePath, false, false)
    .Build();
//...
config.GetSection("apiClientOptions").GetSection(apiClientName).Bind(apiClientOptions);

字符串
HttpApiClientOptions类:

public class HttpApiClientOptions : BaseApiClientOptions
{
    public string Url { get; set; }

    public Dictionary<string, string>? Headers { get; set; }

    public Dictionary<string, string>? Params { get; set; }

    public Dictionary<string, object>? Body { get; set; }
}


JSON配置:

{
    "url": "https://example.com",
    "headers": {
        "Authorization": "Bearer sk-"
    },
    "params": {},
    "body": {"model": "gpt-3.5-turbo", "messages": [{"role":"user", "content":"hello!"}], "temperature": 0.7}
}


我试图将**Body定义为JObjectJsonElement,但这种方法也无法从第一层嵌套中检索值。
我没有将整个
Body节点Map到特定类型的原因是Body节点下的内容和嵌套深度不确定。有没有办法让程序在配置过程中从JSON文件中读取body**节点内部的所有信息?

vxf3dgd4

vxf3dgd41#

现在,我还将Body定义为Dictionary<string, string>,其中的值包含Body节点下的原始内容。但是,在填写JSON配置文件时,这种方法变得非常麻烦。有没有更好的方法来做到这一点?
JSON配置文件中的“body”字段示例:

"body": "{\"model\": \"gpt-3.5-turbo\", \"messages\": [{\"role\": \"user\", \"content\": \"hello!\"}], \"temperature\": 0.7}"

字符串

vzgqcmou

vzgqcmou2#

你应该明白一件事,配置不是JSON,它是键值对的集合,JSON文件不是配置的单一来源。从the docs开始:
.NET中的配置使用一个或多个配置提供程序执行。配置提供程序使用各种配置源从键值对读取配置数据:

  • 设置文件,如appsettings.json
  • 环境变量
  • 命令行参数
  • ...

所以Dictionary<string, object>对binder来说没有太大意义。一个选项-为所有级别提供实际类型:

public class HttpApiClientOptions 
{
    public string Url { get; set; }
    public Dictionary<string,string> Headers { get; set; }
    public Dictionary<string,string> Params { get; set; }
    public Body Body { get; set; }
}

public class Body
{
    public string Model { get; set; }
    public List<Message> Messages { get; set; } // or List<Dictionary<string,string>>
    public double Temperature { get; set; }
}

public class Message
{
    public string Role { get; set; }
    public string Content { get; set; }
}

字符串
另一种方法是从模型中排除Body,并通过GetChildren从某个点动态读取配置并处理结果:

public class HttpApiClientOptions 
{
    public string Url { get; set; }
    public Dictionary<string,string> Headers { get; set; }
    public Dictionary<string,string> Params { get; set; }
}


还有

var body = builder.Configuration.GetSection("Body");
foreach (var section in body.GetChildren())
{
    // recursively process section
}

bd1hkmkf

bd1hkmkf3#

native config反序列化只适用于一个级别。如果你有一个嵌套的对象,最好使用这个语法

var json = File.ReadAllText(configFilePath);

  var result = JObject.Parse(json)["apiClientOptions"]
                      .ToObject<HttpApiClientOptions>();

字符串
试验,试验

string role = (string) ((JArray) result.Body["messages"])[0]["role"]; // "user"

相关问题