zoukankan      html  css  js  c++  java
  • golang depth read map

    Foreword: I optimized and improved the below solution, and released it as a library here: github.com/icza/dyno.


    The cleanest way would be to create predefined types (structures struct) that model your JSON, and unmarshal to a value of that type, and you can simply refer to elements using Selectors (for struct types) and Index expressions (for maps and slices).

    However if your input is not of a predefined structure, I suggest you the following 2 helper functions: get() and set(). The first one accesses (returns) an arbitrary element specified by an arbitrary path (list of string map keys and/or int slice indices), the second changes (sets) the value specified by an arbitrary path (implementations of these helper functions are at the end of the answer).

    You only have to include these 2 functions once in your project/app.

    And now using these helpers, the tasks you want to do becomes this simple (just like the python solution):

    fmt.Println(get(d, "key3", 0, "c2key1", "c3key1"))
    set("NEWVALUE", d, "key3", 0, "c2key1", "c3key1")
    fmt.Println(get(d, "key3", 0, "c2key1", "c3key1"))

    Output:

    change1
    NEWVALUE

    Try your modified app on the Go Playground.

    Note - Further Simplification:

    You can even save the path in a variable and reuse it to simplify the above code further:

    path := []interface{}{"key3", 0, "c2key1", "c3key1"}
    
    fmt.Println(get(d, path...))
    set("NEWVALUE", d, path...)
    fmt.Println(get(d, path...))

    And the implementations of get() and set() are below. Note: checks whether the path is valid is omitted. This implementation uses Type switches:

    func get(m interface{}, path ...interface{}) interface{} {
        for _, p := range path {
            switch idx := p.(type) {
            case string:
                m = m.(map[string]interface{})[idx]
            case int:
                m = m.([]interface{})[idx]
            }
        }
        return m
    }
    
    func set(v interface{}, m interface{}, path ...interface{}) {
        for i, p := range path {
            last := i == len(path)-1
            switch idx := p.(type) {
            case string:
                if last {
                    m.(map[string]interface{})[idx] = v
                } else {
                    m = m.(map[string]interface{})[idx]
                }
            case int:
                if last {
                    m.([]interface{})[idx] = v
                } else {
                    m = m.([]interface{})[idx]
                }
            }
        }
    }
  • 相关阅读:
    ORACLE SEQUENCE 介绍
    cocos2d 游戏开发:Cocos2d v3 "hello world"+显示飞船
    无线网络覆盖
    解决xShell4某些情况下按删除键会输出^H的问题
    Android开发经验之—intent传递大数据
    简单的REST的框架实现
    ListView 使用方法(Asp.Net)
    POJ2528 Mayor's posters 【线段树】+【成段更新】+【离散化】
    C#反射Assembly 具体说明
    HDU 4432 Sum of divisors (进制模拟)
  • 原文地址:https://www.cnblogs.com/ExMan/p/11461159.html
Copyright © 2011-2022 走看看