使用JSON.Net如何序列化动态并强制所有字符串值为小写?

时间:2017-08-25 16:45:26

标签: c# json serialization json.net azure-cosmosdb

在我正在序列化到文档数据库的对象中,我有一个动态属性,它需要以小写形式写入的所有字符串值以用于索引。我尝试使用自定义转换器,但这需要我编写几种不同类型的序列化代码。我想要的只是标准的序列化行为,但是字符串值被强制为小写。鉴于Newtonsoft库的灵活性,这似乎应该是直截了当的,我还没有找到合适的界面。

请注意,我没有对序列化的直接控制。我写信给Azure COSMOSDB,他们的客户端库使用JSON.Net进行序列化。我可以传入一个自定义序列化器来使用。

更新

以下似乎有效。步骤是:

  1. 添加代码以通过JToken.FromObject()
  2. 填充动态属性
  3. 使用下面的代码强制所有字符串值为小写(数组很棘手)
  4. 将对象发送到CosmosDB

    private static JToken JTokenStringValuesToLower(JToken startToken)
    {
        Stack<JEnumerable<JToken>> tokenStack = new Stack<JEnumerable<JToken>>();
        tokenStack.Push(startToken.Children());
    
        while (tokenStack.Count != 0)
        {
            JEnumerable<JToken> children = tokenStack.Pop();
    
            foreach (JToken child in children)
            {
                if (child.Type == JTokenType.Property)
                {
                    JProperty property = (JProperty)child;
    
                    if (child.HasValues)
                    {
                        tokenStack.Push(child.Children());
                    }
    
                    if (property.Value.Type == JTokenType.String)
                    {
                        property.Value = property.Value.ToString().ToLowerInvariant();
                    }
                }
                else if (child.Type == JTokenType.Array && child.HasValues)
                {
                    JArray array = (JArray)child;
                    JToken[] arrayItems = new JToken[array.Count];
                    int idx = 0;
                    bool modified = false;
    
                    foreach (JToken arrayItem in array.Children())
                    {
                        arrayItems[idx++] = arrayItem;
                    }
    
                    for (int i = 0; i < arrayItems.Length; ++i)
                    {
                        JToken token = arrayItems[i];
    
                        if (token.Type == JTokenType.String)
                        {
                            modified = true;
                            arrayItems[i] = token.ToString().ToLowerInvariant();
                        }
                    }
    
                    if (modified)
                    {
                        array.Clear();
    
                        foreach (JToken item in arrayItems)
                        {
                            array.Add(item);
                        }
                    }
                }
                else if (child.HasValues)
                {
                    tokenStack.Push(child.Children());
                }
            }
        }
    
        return startToken;
    }
    

1 个答案:

答案 0 :(得分:0)

对于类似的问题,我发现使用JToken非常强大,因为this example(SO)显示了如何迭代JSON数据结构并根据类型或内容操纵每个数据节点。