CosmosSerializer 自定义 json 序列化以剪裁字符串值

CosmosSerializer custom json serialization to trim string values

提问人:ben 提问时间:11/10/2023 最后编辑:ben 更新时间:11/13/2023 访问量:61

问:

我正在尝试创建一个自定义 CosmosSerializer,该程序在序列化和反序列化(读取和写入 cosmos 容器)期间从属性值中修剪所有空格。本质上,我有一个容器,其中包含某些值周围有多余的空格的 json 文档,我想在阅读文档时忽略空格,并防止任何空格在编写文档时进入任何值。

我创建了一个 CosmosSerializer 并将其传递到 CosmosClient 实例化中:

var cosmosClientOptions = new CosmosClientOptions
{
     ConnectionMode = ConnectionMode.Direct,
     RequestTimeout = new TimeSpan(10),
     Serializer = new CustomCosmosSerializer()
};

private readonly CosmosClient _cosmosClient = new CosmosClient(uri, key, cosmosClientOptions);
    

到目前为止,我的 CosmosSerializer 如下所示:

public class CustomCosmosSerializer: CosmosSerializer
{
    private readonly Newtonsoft.Json.JsonSerializer _serializer = new();

    public override T FromStream<T>(Stream stream)
    {
        //go from stream to object of type T
        //trim all excess whitespace of all string property values along the way
        return _serializer.Deserialize<T>(new JsonTextReader(new StreamReader(stream)));
    
    }

    public override Stream ToStream<T>(T input)
    {
        //go from object to stream
        //trim all excess whitespace of all string property values along the way
    
        using var stringWriter = new StringWriter();
        using var jsonTextWriter = new JsonTextWriter(stringWriter);
        _serializer.Serialize(jsonTextWriter, input, input.GetType());

        return new MemoryStream(Encoding.UTF8.GetBytes(stringWriter.ToString()));
    }
}

但是,我不确定在序列化/反序列化期间应用所需的空格修整的最高性能策略。我尝试过利用反射来获取和分析属性值,但我担心性能,并对更好的策略感到好奇。谢谢!

C# JSON json.net azure-cosmosdb

评论

1赞 Steven B. 11/10/2023
我会创建一个这样的转换器,然后将其添加到您的 Newtonsoft 序列化程序设置中。

答:

0赞 Balaji 11/13/2023 #1

根据此 MSDOC,您可以使用方法来修剪字符串值。.Trim

我在下面的代码中使用了这种方法来修剪字符串值。它用于在字符串属性的 JSON 序列化和反序列化期间修剪空格。我在下面的代码中使用了在反序列化过程中修剪空格的方法。ReadJson

我插入了一些示例项目,包括 Id、Name 和 Dept,其中 NameDept 由空格组成,这些空格被使用方法删除,如下面的代码所示。.Trim()

我尝试使用的代码:

public class TrimmingConverter : JsonConverter
{
    public override bool CanRead => true;
    public override bool CanWrite => false;

    public override bool CanConvert(Type objectType) => objectType == typeof(string);

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        return ((string)reader.Value)?.Trim();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

public class Person
{
    [JsonProperty("id")] 
    [JsonConverter(typeof(TrimmingConverter))]
    public string Id { get; set; }

    [JsonProperty("name")]
    [JsonConverter(typeof(TrimmingConverter))]
    public string Name { get; set; }

    [JsonProperty("dept")]
    [JsonConverter(typeof(TrimmingConverter))]
    public string Dept { get; set; }
}

class Program
{
    static async Task Main()
    {
        string endpointUrl = "****";
        string authorizationKey = "****";
        string databaseId = "newdb";
        string containerId = "thirdCont";

        CosmosClient client = new CosmosClient(endpointUrl, authorizationKey);
        Container container = client.GetContainer(databaseId, containerId);
 
        var sampdata = "{ ""id"": ""1"", ""name"":"" Balaji "", ""dept"":"" IT "" }";
        var prsn = JsonConvert.DeserializeObject<Person>(sampdata);
 
        await StorePersonData(container, prsn);
        Console.WriteLine("Data has been stored successfully!");
    }

    static async Task StorePersonData(Container container, Person person)
    {
        person.Id = person.Id?.Trim();
        person.Name = person.Name?.Trim();
        person.Dept = person.Dept?.Trim();

        var sampdata = JsonConvert.SerializeObject(person, Formatting.None, new TrimmingConverter());        
        var trimmedPerson = JsonConvert.DeserializeObject<Person>(sampdata);       
        await container.CreateItemAsync(trimmedPerson, new PartitionKey(trimmedPerson.Id));
    }
}

输出:在控制台中:Data has been stored successfully!

在 Azure Cosmos DB 容器中:

{
    "id": "1",
    "name": "Balaji",
    "dept": "IT"
}

此处,namedept 键的值没有任何空格。