当前位置: 首页 > 面试题库 >

JSON字符串的交集

顾学真
2023-03-14
问题内容

我正在尝试找到一种方法来将一个JSON字符串用作各种“模板”以应用于另一个JSON字符串。例如,如果我的模板如下所示:

{
   "id": "1",
   "options": {
      "leatherseats": "1",
      "sunroof": "1"
   }
}

然后将其应用于以下JSON字符串:

{
   "id": "831",
   "serial": "19226715",
   "options": {
      "leatherseats": "black",
      "sunroof": "full",
      "fluxcapacitor": "yes"
   }
}

我想要如下所示的结果JSON字符串:

{
   "id": "831",
   "options": {
      "leatherseats": "black",
      "sunroof": "full",
   }
}

不幸的是,我既不能依赖模板也不可以是固定格式的输入,因此我无法编组/解组到已定义的接口中。

我已经编写了一个遍历模板的递归函数,以构造一个带有每个要包含的节点名称的字符串切片。

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
}

我称这个函数如下:

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)对在目标映射中生成一个条目,如下所示:

  • 如果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(在Go Playground上尝试):

{
  "id": "831",
  "options": {
    "leatherseats": "black",
    "sunroof": "full"
  }
}

笔记:

该解决方案 假定
源映射符合模板。也就是说,如果模板包含某个键的映射,则源映射也应包含相同键的映射。如果不能保证,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字符串: 我只想要和。我试过这样的方法: 但我得到了以下错误: 我只使用过几次JSON。有人能帮我吗? 对我来说最好的例子是这样的,我在另一个例子中做过: 可能吗? 现在我已经做到了: 我试着这样做: 然后: 但现在当我做一个Prtinout时,我会得到和以前一样的错误:

  • 问题内容: 而不是从json字符串中使用$ .parseJSON,我需要获取对象并将其存储在变量中作为代表json的字符串。 (我正在处理的库期望使用格式错误的json类型,因此我需要弄乱它才能使其正常工作。) 最好的方法是什么? 问题答案: 编辑: 您应该使用Douglas Crockford的json2.js库,而不是实现下面的代码。它提供了一些额外的功能以及更好/更旧的浏览器支持。 从以下位

  • JSON 的字符串(string)跟C或者Java的字符串非常相似,是由双引号包围的任意数量Unicode字符的集合,使用反斜线转义。如图 1‑2所示: 图1-2 JSON字符串 由于JSON 字符串不能使用单引号,因此一个字符(character)就是一个单独的字符串(character string)。

  •  说明 调用方法: $.f2e.util.json2str(json); 函数说明: json转字符串 参数说明: 参数名 类型 说明 备注 json object json格式数据 无 脚本 <script> var a = {a:1,b:2,c:3} $.f2e.util.json2str(a) </script>

  • 问题内容: 有什么方法可以让TypeScript枚举与JSON中的字符串兼容? 例如: 我 想 是真的。更具体地说,我希望可以将值定义为 字符串 ,而不是数字。 我知道我可以使用,但这很麻烦,而且似乎使枚举类型注释变得混乱和误导,从而违背了它的目的。JSON从技术上讲 不会 提供有效的枚举值,因此我不应该在枚举中键入属性。 所以我目前正在做的是使用带有静态常量的字符串类型: 这为我提供了我想要的用

  • 问题内容: 我正在寻找一种在字符串中查找JSON数据的方法。像wordpress简码一样思考它。我认为最好的方法是使用正则表达式。我不想解析JSON,只需查找所有出现的事件。 正则表达式中是否有办法使括号的数量匹配?目前,当我嵌套对象时遇到了这个问题。 演示的快速示例: 结果,我想要两个JSON字符串。谢谢! 问题答案: 从给定的文本中提取JSON字符串 由于您正在寻找一种简单的解决方案,因此可以