【问题标题】:json find parent node of node where key named "id" equal to "value"json找到键名“is”等于“value”的节点的父节点
【发布时间】:2014-06-06 07:37:49
【问题描述】:

我有与此类似的 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 中,我如何到达元素的父节点,其中键为 id,值是 node4 或其他内容。

在 xcode 中,我试图解析来自 MVC web API 的 JSON 数据。

我的web.api JSON 是this

当我注释掉 Newtonsoft.Json.PreserveReferencesHandling.Objects 时,JSON 变得非常大,通常像 35MB。

当我使用 PreserveReferencesHandling.Objects 时,.net 会使用 idref 键来重复对象。

在 JSON 中旅行时,如果到达带有值 asdfgref 键,我必须使用键 id 和值 `asdf 搜索返回节点。

Xcode 可以这样做吗?

【问题讨论】:

    标签: ios objective-c json asp.net-web-api


    【解决方案1】:

    您需要进行深度优先或广度优先搜索,具体取决于您认为哪个会最快找到节点。这是您需要的代码的未经测试的尝试:

    深度优先

    - (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
    

    【讨论】:

    • 不错的递归算法解决方案,但不完全是。没有任何预建搜索功能,我可以使用@“id”键获取所有节点。我将如何到达找到的节点的父节点?我正在寻找类似 dom 搜索的东西!
    • 不,没有内置方法。我更新了代码,让你更喜欢。
    猜你喜欢
    • 2015-07-10
    • 2012-08-15
    • 2011-03-21
    • 2021-07-16
    • 2010-12-08
    • 2013-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多