json.net自定义Jobject反序列化 [英] json.net custom jobject deserialization

查看:219
本文介绍了json.net自定义Jobject反序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用JsonConvert.DeserializeObject(string)将字符串反序列化为Jobject,该Jobject可以与dynamic一起动态访问json文档.但是我想避免知道文档的大小写,所以我可以键入

I'm trying to use JsonConvert.DeserializeObject(string) to deserialize a string into an jobject that can use with dynamic to access the json document on the fly. However I want to avoid knowing the casing of the document so I can type

dynamic document = JsonConvert.DeserializeObject(someString);
Console.WriteLine(document.some.path.here.name);

并使其在{"Some":{"path":{"HERE":{"Name":"test"}}}上运行 我找不到如何为自己创建json.net的自定义类的方法,基本上可以删除jobject上的区分大小写(或者可以将所有属性转换为小写)

and have it work on {"Some":{"path":{"HERE":{"Name":"test"}}} I can't find out how to create a custom class for json.net that will do that for me, basically removing case sensitivity on the jobject (or maybe transform all properties to lower case)

推荐答案

要将JToken层次结构中的所有属性递归转换为小写,可以使用以下扩展方法:

To recursively convert all properties in a JToken hierarchy to lower case, you can use the following extension method:

public static class JsonExtensions
{
    public static TJToken RenamePropertiesToLowerInvariant<TJToken>(this TJToken root) where TJToken : JToken
    {
        return root.RenameProperties(s => s.ToLowerInvariant());
    }

    public static TJToken RenameProperties<TJToken>(this TJToken root, Func<string, string> map) where TJToken : JToken
    {
        if (map == null)
            throw new ArgumentNullException();
        if (root == null)
            return null;
        if (root is JProperty)
        {
            return RenameReplaceProperty(root as JProperty, map, -1) as TJToken;
        }
        else
        {
            foreach (IList<JToken> obj in root.DescendantsAndSelf().OfType<JObject>())
                for (int i = obj.Count - 1; i >= 0; i--)
                    RenameReplaceProperty((JProperty)obj[i], map, i);
            return root;
        }
    }

    public static IEnumerable<JToken> DescendantsAndSelf(this JToken node)
    {
        if (node == null)
            return Enumerable.Empty<JToken>();
        var container = node as JContainer;
        if (container != null)
            return container.DescendantsAndSelf();
        else
            return new[] { node };
    }

    private static JProperty RenameReplaceProperty(JProperty property, Func<string, string> map, int index)
    {
        // JProperty.Name is read only so it will need to be replaced in its parent.
        if (property == null)
            return null;
        var newName = map(property.Name);
        if (newName == property.Name)
            return property;
        var value = property.Value;
        // Setting property.Value to null on the old property prevents the child JToken hierarchy from getting recursively cloned when added to the new JProperty
        // See https://github.com/JamesNK/Newtonsoft.Json/issues/633#issuecomment-133358110
        property.Value = null; 
        var newProperty = new JProperty(newName, value);
        IList<JToken> container = property.Parent;
        if (container != null)
        {
            if (index < 0)
                index = container.IndexOf(property);
            container[index] = newProperty;
        }
        return newProperty;
    }
}

然后做

dynamic document = JsonConvert.DeserializeObject<JToken>(someString).RenamePropertiesToLowerInvariant();

但是, JObject 区分大小写,并且没有提供构造函数在其 JObjectDynamicProxy.TryGetMember() 似乎是在进行简单查找,而不区分大小写.

However, JObject is case sensitive and provides no constructor to use a case-invariant comparer in its JPropertyKeyedCollection. And JObjectDynamicProxy.TryGetMember() seems to be doing a simple lookup not a case-insensitive search.

因此,除非您能够获得此答案起作用,否则,如果您需要不区分大小写的动态对象,则可以从>如何将ExpandoObject的字典设置为不区分大小写?然后创建您自己的 ExpandoObjectConverter 反序列化您的替代expando类型.

So, unless you can get this answer to work, if you need a case-insensitive dynamic object, you could take one of the replacements for ExpandoObject from How to set ExpandoObject's dictionary as case insensitive? then create your own version of ExpandoObjectConverter to deserialize your alternative expando type.

这篇关于json.net自定义Jobject反序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆