dsjj15012 2018-07-30 10:50
浏览 76
已采纳

合并两个带有公共密钥golang的JSON数组

it's days I try to merge two jons based on a common key. I have in input two different JSONs with a common field, I would like to merge the data of the two json based on the common key. A sort of sql join between the two JSON.

JSON derives from this code

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"]}

the JSONs in input have this form

{"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"}]

If i have two json like this the result of the function it should be

{"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"}]

if it can help, this is a function I use for merge between two single-value JSONs, but I could not modify it in the right way

    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
    }

Please, Help Me. THX

  • 写回答

1条回答 默认 最新

  • dongye4192 2018-07-30 17:08
    关注

    One observation here is that you can define a simple type that will model both of your data sets and use the golang type system to your advantage (instead of working against it by using so much reflection), for example:

    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)
    

    Now your "merge" function can simply return a new "Data" struct with values populated from the two inputs without having to worry about type assertions or casting. One key feature of this implementation is that it creates a lookup table of data result objects by their "DESC" key, which is later used for correlation:

    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
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog