You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET OpenSearch客户端序列化器如何实现自定义JSON转换?

在.NET OpenSearch客户端中实现字符串/字符串列表的自动转换

问题背景

我的OpenSearch中存在不一致的数据:某个属性的值有时是单个字符串,有时是字符串列表,且无法控制这种数据格式。在使用System.Text.Json序列化器时,我可以通过自定义JSON转换器将字符串列表自动转为逗号分隔的字符串,只需在目标属性上添加特性即可。现在需要在.NET的OpenSearch客户端中实现相同功能。

解决方案

.NET OpenSearch客户端(OpenSearch.Client)支持配置使用System.Text.Json作为序列化器,你可以复用现有的自定义转换器,只需在客户端初始化时配置对应的序列化选项,或直接在属性上保留原有的特性标记。

步骤1:保留原有的自定义转换器

继续使用你已实现的ListOfStringToStringConverter,同时修正一处JSON规范问题:

using Serilog;
using System;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace myProject
{
    public class ListOfStringToStringConverter : JsonConverter<string>
    {
        public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            if (reader.TokenType == JsonTokenType.Null) return null;
            string strValue = "";
            try
            {
                if (JsonTokenType.String == reader.TokenType)
                {
                    strValue = reader.GetString();
                    return strValue;
                }
                else if (JsonTokenType.StartArray == reader.TokenType)
                {
                    reader.Read();
                    string val = "";
                    int i = 0;
                    while (reader.TokenType != JsonTokenType.EndArray)
                    {
                        if (i != 0) val += ",";
                        val += reader.GetString();
                        i++;
                        reader.Read();
                    }
                    return val;
                }
            }
            catch (Exception e)
            {
                Log.Error(e, "反序列化JSON值到属性时出错,属性值将设为null");
            }
            return null;
        }

        public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
        {
            if (value == null)
            {
                writer.WriteNullValue();
            }
            else
            {
                writer.WriteStringValue(value);
            }
        }
    }
}

注:修正了原代码中把null序列化为字符串"null"的问题,改为符合JSON规范的WriteNullValue()。

步骤2:在实体类属性上保留特性标记

继续在目标属性上添加JsonConverter特性,指定使用自定义转换器:

[System.Text.Json.Serialization.JsonConverter(typeof(ListOfStringToStringConverter))]
public string? ItUsedToBeAList { get; set; }

步骤3:配置OpenSearch客户端使用System.Text.Json序列化器

初始化OpenSearchClient时,通过OpenSearchClientSettings指定使用System.Text.Json作为序列化器,并传入包含自定义转换器的JsonSerializerOptions:

using OpenSearch.Client;
using System.Text.Json;

// 创建JsonSerializerOptions并添加自定义转换器
var jsonOptions = new JsonSerializerOptions();
jsonOptions.Converters.Add(new ListOfStringToStringConverter());

// 配置OpenSearch客户端连接与序列化设置
var settings = new OpenSearchClientSettings(new Uri("http://your-opensearch-url:9200"))
    .UseSystemTextJson(jsonOptions);

// 初始化OpenSearch客户端实例
var client = new OpenSearchClient(settings);

替代方案:全局注册转换器(无需属性特性)

如果希望该转换器对所有字符串类型属性生效,可以跳过属性上的特性标记,直接将转换器添加到全局的JsonSerializerOptions中,客户端在序列化/反序列化所有字符串属性时都会自动应用该逻辑。

验证逻辑

当OpenSearch返回的ItUsedToBeAList字段是单个字符串时,会直接赋值给属性;如果是字符串数组,转换器会自动拼接为逗号分隔的字符串;遇到空值或解析错误时,属性会被设为null并记录错误日志。

内容的提问来源于stack exchange,提问作者LilacBlue

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 02:07:19