【问题标题】:merge two JSON arrays with a common key golang合并两个 JSON 数组和一个公共键 golang
【发布时间】:2019-01-06 14:33:39
【问题描述】:

这是我尝试基于一个公共键合并两个 jons 的日子。我输入了两个具有公共字段的不同 JSON,我想根据公共键合并两个 json 的数据。两种 JSON 之间的一种 sql 连接。

JSON 派生自此代码

func Dati_plus(c *gin.Context) {

oracle, err := http.Get("http://XXXX/XXX")
    if err != nil {
            panic(err)
    }
defer oracle.Body.Close()

mysql, err := http.Get("http://XXXX/XXX")
if err != nil {
        panic(err)
}
defer mysql.Body.Close()

oracleJSON, err := ioutil.ReadAll(oracle.Body)
if err != nil {
        panic(err)
}
mysqlJSON, err := ioutil.ReadAll(mysql.Body)
if err != nil {
        panic(err)
}

var oracleOUT map[string]interface{}
var mysqlOUT map[string]interface{}

json.Unmarshal([]byte(oracleJSON), &oracleOUT)
json.Unmarshal([]byte(mysqlJSON), &mysqlOUT)

a := map[string]interface{}{"result":mysqlOUT["result"]}
b := map[string]interface{}{"result":oracleOUT["result"]}

输入中的 JSON 具有这种形式

{"count":2,"result":[{"DESC":"2","NOMEmy":"PIPPO","COGNOMEmy":"PIPPO"},{"DESC":"7","NOMEmy":"PIPPO","COGNOMEmy":"PIPPO"}]

{"count":2,"result":[{"DESC":"2","COS":"PIPPO","ROS":"PIPPO"},{"DESC":"7","COS":"PIPPO","ROS":"PIPPO"},{"DESC":"60","COS":"PIPPO","ROS":"PIPPO"}]

如果我有两个这样的 json 函数的结果应该是

{"count":2,"result":[{"DESC":"2","COS":"PIPPO","ROS":"PIPPO","NOMEmy":"PIPPO","COGNOMEmy":"PIPPO"},{"DESC":"7","COS":"PIPPO","ROS":"PIPPO","NOMEmy":"PIPPO","COGNOMEmy":"PIPPO"},{"DESC":"60","COS":"PIPPO","ROS":"PIPPO"}]

如果有帮助,这是我用于合并两个单值 JSON 的函数,但我无法以正确的方式修改它

    func merge(dst, src map[string]interface{}, depth int) map[string]interface{} {
    if depth > MaxDepth {
        panic("Troppo Lungo")
    }
    for key, srcVal := range src {
        if dstVal, ok := dst[key]; ok {
            srcMap, srcMapOk := mapify(srcVal)
            dstMap, dstMapOk := mapify(dstVal)
            if srcMapOk && dstMapOk {
                srcVal = merge(dstMap, srcMap, depth+1)
            }
        }
        dst[key] = srcVal
    }
    return dst
}

    func mapify(i interface{}) (map[string]interface{}, bool) {
        value := reflect.ValueOf(i)
        if value.Kind() == reflect.Map {
            m := map[string]interface{}{}
            for _, k := range value.MapKeys() {
                m[k.String()] = value.MapIndex(k).Interface()
            }
            return m, true
        }
        return map[string]interface{}{}, false
    }

请帮帮我。谢了

【问题讨论】:

  • 为什么在这里投反对票?这个问题的措辞似乎很好,包括代码和示例数据,而且似乎适合这个社区......
  • 我不知道。感谢支持人员

标签: arrays json go interface


【解决方案1】:

这里的一个观察结果是,您可以定义一个简单的类型,该类型将对您的两个数据集进行建模并使用 golang 类型系统来发挥您的优势(而不是通过使用如此多的反射来对抗它),例如:

type Data struct {
  Count   int                 `json:"count"`
  Results []map[string]string `json:"result"`
}

// ...
oracleData, mysqlData := Data{}, Data{}
err := json.Unmarshal([]byte(oracleJson), &oracleData)
check(err)
err := json.Unmarshal([]byte(mysqlJson), &mysqlData)
check(err)

现在,您的“合并”函数可以简单地返回一个新的“数据”结构,其中包含从两个输入填充的值,而不必担心类型断言或强制转换。此实现的一个关键特性是它通过其“DESC”键创建数据结果对象的查找表,稍后用于关联:

func merge(d1, d2 Data) Data {
  // Create the lookup table by each result object "DESC".
  d1ResultsByDesc := map[string]map[string]string{}
  for _, obj1 := range d1.Results {
    d1ResultsByDesc[obj1["DESC"]] = obj1
  }

  newData := Data{}
  for _, obj2 := range d2.Results {
    newObj := map[string]string{}
    // Include all result data objects from d2
    for k2, v2 := range obj2 {
      newObj[k2] = v2
    }
    // Also include the matching result data from d1
    obj1 := d1ResultsByDesc[obj2["DESC"]]
    for k1, v1 := range obj1 {
      newObj[k1] = v1
    }
    newData.Results = append(newData.Results, newObj)
  }

  return newData
}

【讨论】:

  • 我得到了我想要的东西。非常感谢
猜你喜欢
  • 2019-11-11
  • 1970-01-01
  • 2012-08-16
  • 1970-01-01
  • 2017-06-02
  • 1970-01-01
  • 2018-05-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多