我有类似的JSON 许多id和ref键:
jSon = {
"id":"node1",
"name":"Languages",
"rel":"",
"children":1,
"step":1,
"path":1,
"nodes":[
{
"id":"node2",
"name":"Java",
"rel":"Pure Object Oriented Prog",
"children":1,
"step":2,
"path":2,
"nodes":[
{
"id":"node3",
"name":"C#",
"rel":"Framework",
"children":0,
"step":3,
"path":3,
"nodes":[]
},{
"id":"node4",
"name":"C++",
"rel":"OOPS",
"children":0,
"step":3,
"path":4,
"nodes":[]
}]
}]
};
在Objective-C中,如何到达key为id
的元素的父节点,并且值为node4
或其他值。
在xcode中,我正在尝试解析来自MVC
网络API
的JSON数据。
我的web.api
JSON是this
当我评论Newtonsoft.Json.PreserveReferencesHandling.Objects
时,JSON变得非常大,通常像35MB。
当我使用PreserveReferencesHandling.Objects
时,.net会将id
和ref
个键用于重新定位对象。
在JSON旅行时,如果达到值为ref
的{{1}}密钥,则必须使用密钥asdfg
和值“asdf”搜索回节点。
这可能在id
吗?
答案 0 :(得分:0)
您需要先执行深度优先搜索或广度优先搜索,具体取决于您认为哪个节点最快。这是一个非常未经测试的尝试,你需要的代码:
<强>深度优先强>
- (id)nodeWithID:(NSString *)identifier inDict:(NSDictionary *)dict
{
id node = nil;
if ([dict[@"id"] isEqualToString:identifier])
{
node = dict;
}
else
{
// Traverse the inner nodes to perform a depth-first search
for (NSDictionary *innerNode in dict[@"nodes"])
{
node = [self nodeWithID:identifier inDict:innerNode];
// Break once a node is found
if (node != nil)
{
break;
}
}
}
return node;
}
<强>广度优先强>
- (id)nodeWithID:(NSString *)identifier inDict:(NSDictionary *)dict
{
id node = nil;
if ([dict[@"id"] isEqualToString:identifier])
{
node = dict;
}
else
{
// Perform a breadth-first search
NSMutableArray *nextDictionaries = [[NSMutableArray alloc] initWithArray:dict[@"nodes"]];
while (node == nil && [nextDictionaries count] > 0)
{
dict = nextDictionaries[0];
if ([dict[@"id"] isEqualToString:identifier])
{
node = dict;
}
else
{
[nextDictionaries addObjectsFromArray:dict[@"nodes"]];
[nextDictionaries removeObjectAtIndex:0];
}
}
}
return node;
}
*编辑 *
或者,如果您想要在NSDictionary
上创建一个类别:
typedef NS_ENUM(NSUInteger, NSIdentifierSearchOptions) {
NSIdentifierSearchOptionBreadthFirst = 0,
NSIdentifierSearchOptionDepthFirst = 1
};
@interface NSDictionary (IdentifierSearch)
- (id)objectForKeyIdentifier:(NSString *)identifier options:(NSIdentifierSearchOptions)options;
@end
@implementation NSDictionary (IdentifierSearch)
- (id)objectForKeyIdentifier:(NSString *)identifier options:(NSIdentifierSearchOptions)options
{
id object = nil;
switch (options)
{
case NSIdentifierSearchOptionBreadthFirst:
{
object = [[self class] breadthFirstNodeWithID:identifier inDict:self];
break;
}
case NSIdentifierSearchOptionDepthFirst:
{
object = [[self class] depthFirstNodeWithID:identifier inDict:self];
break;
}
}
return object;
}
+ (id)breadthFirstNodeWithID:(NSString *)identifier inDict:(NSDictionary *)dict
{
id node = nil;
if ([dict[@"id"] isEqualToString:identifier])
{
node = dict;
}
else
{
// Perform a breadth-first search
NSMutableArray *nextDictionaries = [[NSMutableArray alloc] initWithArray:dict[@"nodes"]];
while (node == nil && [nextDictionaries count] > 0)
{
dict = nextDictionaries[0];
if ([dict[@"id"] isEqualToString:identifier])
{
node = dict;
}
else
{
[nextDictionaries addObjectsFromArray:dict[@"nodes"]];
[nextDictionaries removeObjectAtIndex:0];
}
}
}
return node;
}
+ (id)depthFirstNodeWithID:(NSString *)identifier inDict:(NSDictionary *)dict
{
id node = nil;
if ([dict[@"id"] isEqualToString:identifier])
{
node = dict;
}
else
{
// Traverse the inner nodes to perform a depth-first search
for (NSDictionary *innerNode in dict[@"nodes"])
{
node = [self depthFirstNodeWithID:identifier inDict:innerNode];
// Break once a node is found
if (node != nil)
{
break;
}
}
}
return node;
}
@end