Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JSON字符串的交集_Json_String_Go - Fatal编程技术网

JSON字符串的交集

JSON字符串的交集,json,string,go,Json,String,Go,我试图找到一种方法,将一个JSON字符串用作某种类型的“模板”,以应用于另一个JSON字符串。例如,如果我的模板如下所示: { "id": "1", "options": { "leatherseats": "1", "sunroof": "1" } } { "id": "831", "options": { "leatherseats": "black", "sunroof": "full", } } te

我试图找到一种方法,将一个JSON字符串用作某种类型的“模板”,以应用于另一个JSON字符串。例如,如果我的模板如下所示:

{
   "id": "1",
   "options": {
      "leatherseats": "1",
      "sunroof": "1"
   }
}
{
   "id": "831",
   "options": {
      "leatherseats": "black",
      "sunroof": "full",
   }
}
template := `my JSON template here`
var result map[string]interface{}
json.Unmarshal([]byte(template), &result)

var nodenames []string
nodenames = append(nodenames, traverseJSON("", result)...)
然后我将其应用于以下JSON字符串:

{
   "id": "831",
   "serial": "19226715",
   "options": {
      "leatherseats": "black",
      "sunroof": "full",
      "fluxcapacitor": "yes"
   }
}
我想要一个结果JSON字符串,如下所示:

{
   "id": "1",
   "options": {
      "leatherseats": "1",
      "sunroof": "1"
   }
}
{
   "id": "831",
   "options": {
      "leatherseats": "black",
      "sunroof": "full",
   }
}
template := `my JSON template here`
var result map[string]interface{}
json.Unmarshal([]byte(template), &result)

var nodenames []string
nodenames = append(nodenames, traverseJSON("", result)...)
不幸的是,我既不能依赖模板,也不能依赖固定格式的输入,因此我无法将其打包/解包到已定义的接口中

我甚至编写了一个递归函数,它遍历模板来构造一个字符串片段,其中包含每个节点的名称

func traverseJSON(key string, value interface{}) []string {
    var retval []string
    unboxed, ok := value.(map[string]interface{})
    if ok {
        for newkey, newvalue := range unboxed {
            retval = append(retval, recurse(fmt.Sprintf("%s.%s", key, newkey), newvalue)...)
        }
    } else {
        retval = append(retval, fmt.Sprintf("%s", key))
    }
    return retval
}
我按如下方式调用此函数:

{
   "id": "1",
   "options": {
      "leatherseats": "1",
      "sunroof": "1"
   }
}
{
   "id": "831",
   "options": {
      "leatherseats": "black",
      "sunroof": "full",
   }
}
template := `my JSON template here`
var result map[string]interface{}
json.Unmarshal([]byte(template), &result)

var nodenames []string
nodenames = append(nodenames, traverseJSON("", result)...)
然后,我准备编写第二个函数,该函数使用这部分节点名从输入的JSON字符串构造JSON字符串,但是没有动力了,我开始认为我可能走错了方向


如果您对此有任何帮助,我们将不胜感激。

只需创建一个函数,根据模板和源地图“克隆”地图即可

解决方案将迭代模板映射的条目,并为每个
(k,v)
对在目标映射中生成一个条目,如下所示:

{
   "id": "1",
   "options": {
      "leatherseats": "1",
      "sunroof": "1"
   }
}
{
   "id": "831",
   "options": {
      "leatherseats": "black",
      "sunroof": "full",
   }
}
template := `my JSON template here`
var result map[string]interface{}
json.Unmarshal([]byte(template), &result)

var nodenames []string
nodenames = append(nodenames, traverseJSON("", result)...)
  • 如果
    v
    不是映射,只需从源映射中获取
    k
    键的值,并在目标中使用该值

  • 如果
    v
    也是一个映射,则递归调用此“克隆器”,新模板映射为
    v
    ,新源为
    k
    键的源值。此递归调用的结果将是目标映射中
    k
    键的值

这就是它的样子:

func procMap(tmpl, src map[string]interface{}) (dst map[string]interface{}) {
    dst = map[string]interface{}{}

    for k, v := range tmpl {
        if innerMap, ok := v.(map[string]interface{}); ok {
            dst[k] = procMap(innerMap, src[k].(map[string]interface{}))
        } else {
            dst[k] = src[k]
        }
    }

    return dst
}
就这些

测试它:

// tmpljson is the template JSON
var tmpl map[string]interface{}
if err := json.Unmarshal([]byte(tmpljson), &tmpl); err != nil {
    panic(err)
}

// srcjson is the source JSON
var src map[string]interface{}
if err := json.Unmarshal([]byte(srcjson), &src); err != nil {
    panic(err)
}

dst := procMap(tmpl, src)

enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", "  ")
if err := enc.Encode(dst); err != nil {
    panic(err)
}
使用您的示例JSON进行输出(在上尝试):

注意事项:

解决方案假定源映射符合模板。也就是说,如果模板包含某个键的映射,那么源映射也应该包含同一个键的映射。如果无法保证这一点,则应通过检查扩展
procMap()
函数,以避免运行时死机,如下所示:

for k, v := range tmpl {
    if innerMap, ok := v.(map[string]interface{}); ok {
        if src2, ok2 := src[k].(map[string]interface{}); ok2 {
            dst[k] = procMap(innerMap, src2)
        } else {
            log.Printf("src is not conform to template at key %q", k)
        }
    } else {
        dst[k] = src[k]
    }
}

还请注意,JSON数组(切片)没有以任何特殊方式处理,这意味着如果模板包含切片,则源中的值按原样使用,如果切片包含映射,则不会发生递归。该解决方案也可以轻松地扩展到处理切片,这是留给读者的一个练习。

感谢这段代码。不过,我希望对嵌套json数组进行增强。我尝试了递归,但没有成功。例如,我希望procMap处理以下json:{“assetId”:“,”lineItems:[{“lineItemId”:“,”Expenses:“,”Date:“,”comment:“[{“userId:”,”comment:“,”timestamp:“},…]”注:我的json有嵌套数组。当前,我的程序对每个数组行调用procMap一次。这会导致在调用之前/之后发生大量转换/恢复、冗余和脏代码。