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 2020长安杯与连接网探
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)