简体   繁体   English

如何有效地提取 C# 中的嵌套 Json 键?

[英]How do I extract nested Json Keys in C# effeciently?

How can I refactor my below method?如何重构我的以下方法? I am calling a Json Schema and returning all the keys along with their types.我正在调用 Json 模式并返回所有键及其类型。 The second foreach is there because Json of type object means there are nested key value pairs.第二个foreach在那里,因为 object 类型的object意味着存在嵌套的键值对。 Below method works fine but I am hoping there is a better way to write it?下面的方法工作正常,但我希望有更好的方法来编写它?

Dictionary<string, Type> GetPropertiesFromDataSchema(JsonSchema schema)
{
    var propMap = new Dictionary<string, Type>();

    foreach (var prop in schema.ActualProperties)
    {
        Type type = prop.Value.Type switch
        {
            JsonObjectType.Boolean => typeof(bool),
            JsonObjectType.Number => typeof(double),
            JsonObjectType.Integer => typeof(long),
            JsonObjectType.Object => typeof(object),
            JsonObjectType.Array => typeof(Array),
            JsonObjectType.String => typeof(string),
            _ => null
        };
        if (type != null)
        {
            propMap.Add(prop.Key, type);
            if (type.FullName == "System.Object")
            {
                string parentkey = prop.Key.ToString();
                foreach (var nestedprop in prop.Value.ActualProperties)
                {
                    type = nestedprop.Value.Type switch
                    {
                        JsonObjectType.Boolean => typeof(bool),
                        JsonObjectType.Number => typeof(double),
                        JsonObjectType.Integer => typeof(long),
                        JsonObjectType.Object => typeof(object),
                        JsonObjectType.Array => typeof(Array),
                        JsonObjectType.String => typeof(string),
                        _ => null
                    };
                    string colName = parentkey + "_" + nestedprop.Key;
                    propMap.Add(colName, type);
                }
            }

        }
    }
    return propMap;
}

Schema which I'm passing to the method is something like this:我传递给该方法的架构是这样的:

{
"$schema": "http://json-schema.org/draft-04/schema#",
    "type": "object",  
    "properties": {
    "PartitionKey": {
        "type": "string"
        },
        "RowKey": {
        "type": "string"
        },
        "Version": {
        "type": "string"
        },       
        "Eest": {
        "type": "object",
        "properties": {
            "Bulls": {
                "type": "integer"
            },
            "Message": {
                "type": "string"
            },
            "Credit": {
                "type": "number"
            },
            "Read": {
                "type": "number"
            },
            "SBin": {
                "type": "string"
            }
        },
        "required": [
            "Bulls",
            "Message",
            "Credit",
            "Read",
            "SBin"
        ]
        },
        "GenericTests": {
        "type": "array"
        },
        "HostVersion": {
        "type": "string"
        },      
        "RawSampleIDData": {
        "type": "array"
        }
},
    "required": [
        "PartitionKey",
        "RowKey",
        "Version",
        "Eest",
        "GenericTests",
        "HostVersion",
        "RawSampleIDData"
    ]
}

Try something like this:尝试这样的事情:

Dictionary<string, Type> GetPropertiesFromDataSchema(JsonSchema schema)
{
    var propMap = new Dictionary<string, Type>();

    foreach (var prop in schema.ActualProperties)
    {
        Type type = GetType(prop);
        if (type != null)
        {
            propMap.Add(prop.Key, type);
            if (type.FullName == "System.Object")
            {
                string parentkey = prop.Key.ToString();
                foreach (var nestedprop in prop.Value.ActualProperties)
                {
                    type = GetType(nestedprop);
                    string colName = parentkey + "_" + nestedprop.Key;
                    propMap.Add(colName, type);
                }
            }

        }
    }
    return propMap;
}

private Type GetType(KeyValuePair<string, JsonSchemaProperty> prop)
{
    return prop.Value.Type switch
    {
        JsonObjectType.Boolean => typeof(bool),
        JsonObjectType.Number => typeof(double),
        JsonObjectType.Integer => typeof(long),
        JsonObjectType.Object => typeof(object),
        JsonObjectType.Array => typeof(Array),
        JsonObjectType.String => typeof(string),
        _ => null
    };
}

Nate's answer is good, but i would take it a step further and move the inner foreach into a recursive call, something like this: Nate 的回答很好,但我会更进一步,将内部 foreach 移动到递归调用中,如下所示:

// Your public method has the schema as input
Dictionary<string, Type> GetPropertiesFromDataSchema(JsonSchema schema) {
    // Create the result dictionary
    var propMap = new Dictionary<string, Type>();

    // Call recursive method
    GetPropertyMap(schema.ActualProperties, propMap);

    return propMap;
}

private void GetPropertyMap(IReadOnlyDictionary<string, JsonSchemaProperty> properties,
   Dictionary<string, Type> propertyMap, string parentKey = null) {
    // Iterate through the properties
    foreach (var prop in properties) {
        var type = GetType(prop);

        // If the type is null (unknown) just skip the next part
        if (type == null) {
            continue;
        }

        // If parent key is specified prefix the key
        // with it otherwise just use the key
        var key = string.IsNullOrEmpty(parentKey) ?
            prop.Key.ToString() :
            parentKey + "_" + prop.Key.ToString();

        // Add property to map
        propertyMap.Add(key, type);

        // If it's an object (I prefer type check instead of string check)
        // Call the same method with the key as the third parameter
        if (type == typeof(object)) {
            GetPropertyMap(prop.Value.ActualProperties, propertyMap, key);
        }
    }
}

// Return the type (Credit: Nate in another answer)
private Type GetType(KeyValuePair<string, JsonSchemaProperty> prop)
{
    return prop.Value.Type switch
    {
        JsonObjectType.Boolean => typeof(bool),
        JsonObjectType.Number => typeof(double),
        JsonObjectType.Integer => typeof(long),
        JsonObjectType.Object => typeof(object),
        JsonObjectType.Array => typeof(Array),
        JsonObjectType.String => typeof(string),
        _ => null
    };
}

EDIT: I added some comments, I hope it helps.编辑:我添加了一些评论,希望对您有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM