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 乌班图ip地址配置及远程SSH
  • ¥15 怎么让点阵屏显示静态爱心,用keiluVision5写出让点阵屏显示静态爱心的代码,越快越好
  • ¥15 PSPICE制作一个加法器
  • ¥15 javaweb项目无法正常跳转
  • ¥15 VMBox虚拟机无法访问
  • ¥15 skd显示找不到头文件
  • ¥15 机器视觉中图片中长度与真实长度的关系
  • ¥15 fastreport table 怎么只让每页的最下面和最顶部有横线
  • ¥15 java 的protected权限 ,问题在注释里
  • ¥15 这个是哪里有问题啊?