我有下面形式的json数据。我想对其进行转换,以流方式将每个记录的键转换为该记录的字段。我的问题:我不知道如何在不截断密钥并将其丢失的情况下进行操作。我已经推断出所需的流结构,请参见底部。
问题:如何在不丢失密钥的情况下将输入数据转换为流?
数据:
jq 'with_entries(.value += {key}) | .[]'
非流式转换使用:
{
"a": 1,
"b": 2,
"key": "foo"
}
{
"a": 1,
"b": 2,
"key": "bar"
}
收益:
jq -ncr --stream 'fromstream(1|truncate_stream(inputs))`
现在,如果我的数据文件非常大,我希望流式传输:
"foo"
问题:这会截断键"bar"
和fromstream(inputs)
。另一方面,不截断流而仅调用--stream
毫无意义:这使得整个jq
部分成为空操作,而. | tostream
则将所有内容读取到内存中。
使用[
[
"foo",
"a"
],
1
]
[
[
"foo",
"b"
],
2
]
[
[
"foo",
"b"
]
]
[
[
"bar",
"a"
],
1
]
[
[
"bar",
"b"
],
2
]
[
[
"bar",
"b"
]
]
[
[
"bar"
]
]
,流的结构如下:
. as $dot | (1|truncate_stream($dot | tostream))
[
[
"a"
],
1
]
[
[
"b"
],
2
]
[
[
"b"
]
]
[
[
"a"
],
1
]
[
[
"b"
],
2
]
[
[
"b"
]
]
被截断时,结构为:
[["foo"]]
因此,为了使我能够按需要的方式构造流,我将不得不生成以下结构(我在完成第一条记录后插入了[
[
"foo",
"a"
],
1
]
[
[
"foo",
"b"
],
2
]
[
[
"foo",
"b"
]
]
[
[
"foo"
]
]
[
[
"bar",
"a"
],
1
]
[
[
"bar",
"b"
],
2
]
[
[
"bar",
"b"
]
]
[
[
"bar"
]
]
):>
jq
将其制成字符串fromstream([ [ "foo", "a" ], 1 ],[ [ "foo", "b" ], 2 ],[ [ "foo", "b" ] ],[["foo"]],[ [ "bar", "a" ], 1 ],[ [ "bar", "b" ], 2 ],[ [ "bar", "b" ] ],[ [ "bar" ] ])
可能会消耗很多,我确实得到了我所需要的(另请参见此处的摘录:https://jqplay.org/s/iEkMfm_u92):
{
"foo": {
"a": 1,
"b": 2
}
}
{
"bar": {
"a": 1,
"b": 2
}
}
收益:
fromstream([ [ "foo", "a" ], 1 ],[ [ "foo", "b" ], 2 ],[ [ "foo", "b" ] ],[["foo"]],[ [ "bar", "a" ], 1 ],[ [ "bar", "b" ], 2 ],[ [ "bar", "b" ] ],[ [ "bar" ] ]) | with_entries(.value += {key}) | .[]
最终结果(请参见https://jqplay.org/s/-UgbEC4BN8)将是:
{
"a": 1,
"b": 2,
"key": "foo"
}
{
"a": 1,
"b": 2,
"key": "bar"
}
屈服
public static void main(String[] args) {
String s = "X";
for (int i = 5; i > 0; i--) {
for (int j = i; j > 0; j--) {
System.out.print(s);
}
System.out.println();
}
}
答案 0 :(得分:2)
jq Cookbook中提供了用于将对象转换为键值对象的通用函数atomize(s)
。使用它,解决问题的方法很简单:
atomize(inputs) | to_entries[] | .value + {key}
({{key}
是{key: .key}
的简写。)
作为参考,这里是def
:
# Convert an object (presented in streaming form as the stream s) into
# a stream of single-key objects
# Example:
# atomize(inputs) (used in conjunction with "jq -n --stream")
def atomize(s):
fromstream(foreach s as $in ( {previous:null, emit: null};
if ($in | length == 2) and ($in|.[0][0]) != .previous and .previous != null
then {emit: [[.previous]], previous: ($in|.[0][0])}
else { previous: ($in|.[0][0]), emit: null}
end;
(.emit // empty), $in
) ) ;