[英]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.