【问题标题】:How to add json objects from file to another json array of objects in another file如何将文件中的json对象添加到另一个文件中的另一个json对象数组中
【发布时间】:2020-11-14 14:06:04
【问题描述】:

在 *nix 环境中。我正在寻找关于如何将文件中的一些(不太有效)json 添加到另一个(有效)json 文件的解决方案。让我详细说明一下,并介绍迄今为止我尝试过的一些失败的尝试。

这将在 shell 脚本中循环运行,该循环会变得非常大。它正在进行一次只能返回 1000 个的 api 调用。但是,总共有 70,000,000 多条记录。因此,我必须调用这个 api 70,000 次才能获得所有需要的记录。我要保留的原始 json 文件,它包含我想要的实际数据之外的信息,例如结果信息和成功消息等。每次我迭代并调用下一组时,我都试图删除该信息并只需将主要数据记录附加到第一组的主要数据记录即可。

我已经完成了 99%。我正在尝试使用 jq sed 和 python。数据记录的主体在技术上不是有效的 json。所以jq 抱怨,因为它只能附加有效数据。我的尝试看起来像这样jq --argjson results "$(<new.json)" '.result[] += [$results]' original.json。但如果是这样,那么它将是有效的 json。

我已经使用grep -n 抽象出我想开始将新记录集附加到第一组记录的行号。所以我一直在尝试使用sed,但无法找出正确的语法。虽然我觉得我很接近。我一直在尝试类似sed -i -e $linenumber '<a few sed things here> new.json' original.json 的东西。但还没有成功。

我现在尝试编写一个python 脚本来执行此操作。但我以前从未尝试过这样的事情。只是在 readlines 和字符串替换上进行了一些字符串匹配。我没有意识到没有用于跳转到特定行的内置方法。我想我可以做一些 find 语句来跳转到 python 中的那一行,但我已经在 bash 脚本中完成了这个。另外,我意识到我可以将python 中的每一行读入内存,但我担心有这么多记录,它可能会变得太多并且变得非常慢。

我对尝试某种head 和tail 有过一些想法,并写在两者之间,因为我知道确切的行号。欢迎使用任何工具/语言的任何想法或解决方案。这是一个 devops 项目,只是为了诊断一些日志,所以我试图不把它变成一个完整的项目,因为一旦我生成了日志,我将把所有的注意力和精力转移到针对这个最终生成的 json 运行命令文件并且不再真正使用此脚本。

original.json 的示例

{
  "result": [
    {
      "id": "5b5915f4cdb39c7b",
      "kind": "foo",
      "source": "bar",
      "action": "baz",
      "matches": [
        {
          "id": "b298ee91704b489b8119c1d604a8308d",
          "source": "blah",
          "action": "buzz"
        }
      ],
      "occurred_at": "date"
    },
    {
      "id": "5b5915f4cdb39c7b",
      "kind": "foo",
      "source": "bar",
      "action": "baz",
      "matches": [
        {
          "id": "b298ee91704b489b8119c1d604a8308d",
          "source": "blah",
          "action": "buzz"
        }
      ],
      "occurred_at": "date"
    }
],
  "result_info": {
    "cursors": {
      "after": "dlipU4c",
      "before": "iLjx06u"
    },
    "scanned_range": {
      "since": "date",
      "until": "date"
    }
  },
  "success": true,
  "errors": [],
  "messages": []
}

new.json 示例

{
  "id": "5b5915f4cdb39c7b",
  "kind": "foo",
  "source": "bar",
  "action": "baz",
  "matches": [
    {
      "id": "b298ee91704b489b8119c1d604a8308d",
      "source": "blah",
      "action": "buzz"
    }
  ],
  "occurred_at": "date"
},
{
  "id": "5b5915f4cdb39c7b",
  "kind": "foo",
  "source": "bar",
  "action": "baz",
  "matches": [
    {
      "id": "b298ee91704b489b8119c1d604a8308d",
      "source": "blah",
      "action": "buzz"
    }
  ],
  "occurred_at": "date"
}

不用担心缩进或缺少尾随逗号,我已经弄清楚并确认工作正常。

【问题讨论】:

  • jq --argjson results "[$(<new.json)]" '.result += $results' original.json 做你想做的事吗?
  • 另外,针对任何认为{...},{...} 是合理返回的东西提交错误报告。
  • 它会,如果它是有效的 json(即{...},{...}),它不是。所以不,它不起作用,它给了我一个错误,它应该,因为它是有道理的。它不是有效的 json。但如果它确实有效,结果将是有效的 json。我想你误解了{...},{...} 是有效的 json。
  • 我知道不是;这就是为什么我在我的建议中将$(<new.json) 包裹在[...] 中,以将其转换为有效数组。
  • 哦,对不起,我错过了。是的,这正是我想要的。非常感谢@chepner

标签: python json bash sed jq


【解决方案1】:

所以首先将结果添加到新文件中创建一个json文件,其中“[]”是一个空数组作为其内容,这是为了确保我们加载的文件是有效的json。 接下来为每个文件运行以下命令作为输入

jq --argjson results "$(<new.json)" '.result | . += $results  '  orig.json > new.json

您的查询的问题是 .result[] 这会单独返回所有元素,而不是格式中的 json 对象

{}
{}

而不是

[
{},
{}
]

【讨论】:

  • 这最初让我明白了,但我确实用 sed 修复了这个问题,添加了问题中包含的逗号。这在技术上也是无效的 json。两个对象之间的逗号jq 抱怨 Expecting 'EOF' 如果你去任何在线 json 验证器并尝试,你会得到相同的结果。这就是为什么我在jq 上也没有成功的原因。
  • 实际上当我们指定 .result 时,它返回的 json 数组对象是合法的 json
  • 嗯....我刚试过jq --argjson results "$(&lt;objects-with-commas.json)" '.result | . += $results ' orig.json &gt; new.json。 orig.json 和 objects-with-commas.json 与上面原始问题帖子中的两个文件中的文件完全相同。我会从 jq 那里得到jq: invalid JSON text passed to --argjson。如果有帮助,我的版本是 jq-1.6。
  • 它不应该有 result_info .....它只是添加了 [ at start 和 ] at end 让它成为一个有效的 json ......你为什么使用 3 个文件替换对象-with-commas json 文件与 new.json 并确保 new.json 具有“[]”作为其文件内容不包含引号
【解决方案2】:

您可以通过将 API 响应中的无效 JSON 包装在 [...] 中来将其转换为有效数组。生成的数组可以直接导入并添加到result 数组中。

jq --argjson results "<b>[</b>$(&lt;new.json)<b>]</b>" '.result += <b>$results</b>' original.json

【讨论】:

    【解决方案3】:

    根据给定的 new.json 及其描述,您似乎有逗号分隔的 JSON 对象,其中 JSON 分隔的逗号位于与正则表达式 '^}、*$' 匹配的单独行上

    如果是这种情况,好消息是您只需删除多余的逗号即可达到您想要的结果:

    sed 's/^}, *$/}/' new.txt
    

    这会产生一个对象流,然后可以通过几种众所周知的方式中的任何一种进行处理(例如,通过使用 -s 选项“啜饮”它)。

    “XY 问题”?

    在旁注中,您写道:

    我确实使用 sed 解决了这个问题,添加了问题中包含的逗号。

    所以听起来好像发布的 Q 真的是所谓的"XY" problem。无论如何,如果您从 JSON 对象流开始,那么当然需要添加逗号并处理后果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多