Remove all null values
I am trying to remove null values from a json object using jq. I found this issue on their github and so now I'm trying to remove them with del
.
I have this:
'{ id: $customerId, name, phones: ([{ original: .phone },
{ original: .otherPhone}]), email} | del(. | nulls)'
This doesn't seem to do anything. However if I replace nulls
with .phones
it does remove the phone numbers.
json bash null jq
add a comment |
I am trying to remove null values from a json object using jq. I found this issue on their github and so now I'm trying to remove them with del
.
I have this:
'{ id: $customerId, name, phones: ([{ original: .phone },
{ original: .otherPhone}]), email} | del(. | nulls)'
This doesn't seem to do anything. However if I replace nulls
with .phones
it does remove the phone numbers.
json bash null jq
1
Please extend this to be complete enough to run, showing input, actual output, and desired output. (For instance, you could provide minimal JSON input in a heredoc, by runningjq '...your code here...' <<'EOF'
, including some JSON that demonstrates the problem, and having anEOF
afterwards). See also the Help Center documentation on Minimal, Complete, Verifiable Examples.
– Charles Duffy
Sep 14 '16 at 22:31
...as it is, it's hard to tell where in your data structure the NULs actually are, which is critical to being able to build or test a solution.
– Charles Duffy
Sep 14 '16 at 22:35
Note that while I'm voting to close the question as it's currently written, (1) it won't actually be closed unless others agree, and (2) editing a closed question automatically puts it into a queue to be considered for reopening, so extending it to include a MCVE should result in that closure being reversed.
– Charles Duffy
Sep 14 '16 at 22:37
@CharlesDuffy - Regarding your comment about "NULs" -- (1) the OP was asking about JSON "null", not "NUL"; (2) to anyone who knows jq, it's clear where the nulls are; (3) to anyone who knows JSON, it's fairly obvious.
– peak
Dec 15 '16 at 18:58
@peak, it's not obvious to me without following the github link to see the data at hand, and questions that only make sense when given out-of-band content are explicitly incomplete here -- that's extremely well-settled on meta, hence, my request for actual input to be included in the question itself. Yes, one could also edit the input data into the question itself -- either of us does that and there's no more grounds for disagreement. That said, asking the OP to do so themselves has the benefit of making it less likely they'll make the same mistake again in the future.
– Charles Duffy
Dec 15 '16 at 20:53
add a comment |
I am trying to remove null values from a json object using jq. I found this issue on their github and so now I'm trying to remove them with del
.
I have this:
'{ id: $customerId, name, phones: ([{ original: .phone },
{ original: .otherPhone}]), email} | del(. | nulls)'
This doesn't seem to do anything. However if I replace nulls
with .phones
it does remove the phone numbers.
json bash null jq
I am trying to remove null values from a json object using jq. I found this issue on their github and so now I'm trying to remove them with del
.
I have this:
'{ id: $customerId, name, phones: ([{ original: .phone },
{ original: .otherPhone}]), email} | del(. | nulls)'
This doesn't seem to do anything. However if I replace nulls
with .phones
it does remove the phone numbers.
json bash null jq
json bash null jq
edited Dec 16 '16 at 6:49
peak
30k83956
30k83956
asked Sep 14 '16 at 22:29
Ela
1,27131527
1,27131527
1
Please extend this to be complete enough to run, showing input, actual output, and desired output. (For instance, you could provide minimal JSON input in a heredoc, by runningjq '...your code here...' <<'EOF'
, including some JSON that demonstrates the problem, and having anEOF
afterwards). See also the Help Center documentation on Minimal, Complete, Verifiable Examples.
– Charles Duffy
Sep 14 '16 at 22:31
...as it is, it's hard to tell where in your data structure the NULs actually are, which is critical to being able to build or test a solution.
– Charles Duffy
Sep 14 '16 at 22:35
Note that while I'm voting to close the question as it's currently written, (1) it won't actually be closed unless others agree, and (2) editing a closed question automatically puts it into a queue to be considered for reopening, so extending it to include a MCVE should result in that closure being reversed.
– Charles Duffy
Sep 14 '16 at 22:37
@CharlesDuffy - Regarding your comment about "NULs" -- (1) the OP was asking about JSON "null", not "NUL"; (2) to anyone who knows jq, it's clear where the nulls are; (3) to anyone who knows JSON, it's fairly obvious.
– peak
Dec 15 '16 at 18:58
@peak, it's not obvious to me without following the github link to see the data at hand, and questions that only make sense when given out-of-band content are explicitly incomplete here -- that's extremely well-settled on meta, hence, my request for actual input to be included in the question itself. Yes, one could also edit the input data into the question itself -- either of us does that and there's no more grounds for disagreement. That said, asking the OP to do so themselves has the benefit of making it less likely they'll make the same mistake again in the future.
– Charles Duffy
Dec 15 '16 at 20:53
add a comment |
1
Please extend this to be complete enough to run, showing input, actual output, and desired output. (For instance, you could provide minimal JSON input in a heredoc, by runningjq '...your code here...' <<'EOF'
, including some JSON that demonstrates the problem, and having anEOF
afterwards). See also the Help Center documentation on Minimal, Complete, Verifiable Examples.
– Charles Duffy
Sep 14 '16 at 22:31
...as it is, it's hard to tell where in your data structure the NULs actually are, which is critical to being able to build or test a solution.
– Charles Duffy
Sep 14 '16 at 22:35
Note that while I'm voting to close the question as it's currently written, (1) it won't actually be closed unless others agree, and (2) editing a closed question automatically puts it into a queue to be considered for reopening, so extending it to include a MCVE should result in that closure being reversed.
– Charles Duffy
Sep 14 '16 at 22:37
@CharlesDuffy - Regarding your comment about "NULs" -- (1) the OP was asking about JSON "null", not "NUL"; (2) to anyone who knows jq, it's clear where the nulls are; (3) to anyone who knows JSON, it's fairly obvious.
– peak
Dec 15 '16 at 18:58
@peak, it's not obvious to me without following the github link to see the data at hand, and questions that only make sense when given out-of-band content are explicitly incomplete here -- that's extremely well-settled on meta, hence, my request for actual input to be included in the question itself. Yes, one could also edit the input data into the question itself -- either of us does that and there's no more grounds for disagreement. That said, asking the OP to do so themselves has the benefit of making it less likely they'll make the same mistake again in the future.
– Charles Duffy
Dec 15 '16 at 20:53
1
1
Please extend this to be complete enough to run, showing input, actual output, and desired output. (For instance, you could provide minimal JSON input in a heredoc, by running
jq '...your code here...' <<'EOF'
, including some JSON that demonstrates the problem, and having an EOF
afterwards). See also the Help Center documentation on Minimal, Complete, Verifiable Examples.– Charles Duffy
Sep 14 '16 at 22:31
Please extend this to be complete enough to run, showing input, actual output, and desired output. (For instance, you could provide minimal JSON input in a heredoc, by running
jq '...your code here...' <<'EOF'
, including some JSON that demonstrates the problem, and having an EOF
afterwards). See also the Help Center documentation on Minimal, Complete, Verifiable Examples.– Charles Duffy
Sep 14 '16 at 22:31
...as it is, it's hard to tell where in your data structure the NULs actually are, which is critical to being able to build or test a solution.
– Charles Duffy
Sep 14 '16 at 22:35
...as it is, it's hard to tell where in your data structure the NULs actually are, which is critical to being able to build or test a solution.
– Charles Duffy
Sep 14 '16 at 22:35
Note that while I'm voting to close the question as it's currently written, (1) it won't actually be closed unless others agree, and (2) editing a closed question automatically puts it into a queue to be considered for reopening, so extending it to include a MCVE should result in that closure being reversed.
– Charles Duffy
Sep 14 '16 at 22:37
Note that while I'm voting to close the question as it's currently written, (1) it won't actually be closed unless others agree, and (2) editing a closed question automatically puts it into a queue to be considered for reopening, so extending it to include a MCVE should result in that closure being reversed.
– Charles Duffy
Sep 14 '16 at 22:37
@CharlesDuffy - Regarding your comment about "NULs" -- (1) the OP was asking about JSON "null", not "NUL"; (2) to anyone who knows jq, it's clear where the nulls are; (3) to anyone who knows JSON, it's fairly obvious.
– peak
Dec 15 '16 at 18:58
@CharlesDuffy - Regarding your comment about "NULs" -- (1) the OP was asking about JSON "null", not "NUL"; (2) to anyone who knows jq, it's clear where the nulls are; (3) to anyone who knows JSON, it's fairly obvious.
– peak
Dec 15 '16 at 18:58
@peak, it's not obvious to me without following the github link to see the data at hand, and questions that only make sense when given out-of-band content are explicitly incomplete here -- that's extremely well-settled on meta, hence, my request for actual input to be included in the question itself. Yes, one could also edit the input data into the question itself -- either of us does that and there's no more grounds for disagreement. That said, asking the OP to do so themselves has the benefit of making it less likely they'll make the same mistake again in the future.
– Charles Duffy
Dec 15 '16 at 20:53
@peak, it's not obvious to me without following the github link to see the data at hand, and questions that only make sense when given out-of-band content are explicitly incomplete here -- that's extremely well-settled on meta, hence, my request for actual input to be included in the question itself. Yes, one could also edit the input data into the question itself -- either of us does that and there's no more grounds for disagreement. That said, asking the OP to do so themselves has the benefit of making it less likely they'll make the same mistake again in the future.
– Charles Duffy
Dec 15 '16 at 20:53
add a comment |
5 Answers
5
active
oldest
votes
The following illustrates how to remove all the null-valued keys from a JSON object:
jq -n '{"a":1, "b": null, "c": null} | with_entries( select( .value != null ) )'
{
"a": 1
}
Alternatively, paths/0
can be used as follows:
. as $o | [paths | {(.) : ($o[.])} ] | add
By the way, del/1
can also be used to achieve the same result, e.g. using this filter:
reduce keys as $k (.; if .[$k] == null then del(.[$k]) else . end)
Or less obviously, but more succinctly:
del( .[ (keys - [paths]) ] )
And for the record, here are two ways to use delpaths/1
:
jq -n '{"a":1, "b": null, "c": null, "d":2} as $o
| $o
| delpaths( [ keys | select( $o[.] == null ) ] | map( [.]) )'
$ jq -n '{"a":1, "b": null, "c": null, "d":2}
| [delpaths((keys - paths) | map([.])) ] | add'
In both these last two cases, the output is the same:
{
"a": 1,
"d": 2
}
What is meant by/1
in the references to functions likedel/1
? I've seen it in other answers here, too, but not in jq's documentation.
– L S
Aug 1 '17 at 13:24
1
It is the arity of the function. The most recent versions of jq have a builtin namedbuiltins
which emits an array of strings of the form FUNCTOR/ARITY
– peak
Aug 1 '17 at 13:49
add a comment |
[WARNING: the definition of walk/1
given in this response is problematic, not least for the reason given in the first comment; note also that jq 1.6 defines walk/1
differently.]
I am adding the new answer to emphasize the extended version of the script by @jeff-mercado. My version of the script assumes the empty values are as follows:
null
;
- empty arrays;
{}
- empty objects.
Removing of empty arrays and objects was borrowed from here https://stackoverflow.com/a/26196653/3627676.
def walk(f):
. as $in |
if type == "object" then
reduce keys as $key
( {}; . + { ($key): ( $in[$key] | walk(f) ) } ) | f
elif type == "array" then
select(length > 0) | map( walk(f) ) | f
else
f
end;
walk(
if type == "object" then
with_entries(select( .value != null and .value != {} and .value != ))
elif type == "array" then
map(select( . != null and . != {} and .!= ))
else
.
end
)
1
Addingselect(length > 0) |
todef walk(f)
is a mistake. For some JSON, it removes non-empty arrays. For other JSON (e.g., nested objects, each including some nulls and empty structures), only{}
was returned. However, the condition shown here works with the original definition ofwalk
. I just noticed this problem, so I can't change the vote I gave yesterday.
– L S
Aug 4 '17 at 15:41
add a comment |
That's not what del/1
was meant to be used for. Given an object as input, if you wanted to remove the .phones
property, you'd do:
del(.phones)
In other words, the parameter to del
is the path to the property you wish to remove.
If you wanted to use this, you would have to figure out all the paths to null
values and pass it in to this. That would be more of a hassle though.
For an easier approach, you'll have to walk through the object tree to find null
values. If found, remove the corresponding property (or otherwise filter it out). Using walk/1
, your filter could be applied recursively to exclude the null
values.
walk(
if type == "object" then
with_entries(select(.value != null))
elif type == "array" then
map(select(. != null))
else
.
end
)
So if you had this for input:
{
"foo": null,
"bar": "bar",
"biz": [1,2,3,4,null],
"baz": {
"a": 1,
"b": null,
"c": ["a","b","c","null",32,null]
}
}
This filter would yield:
{
"bar": "bar",
"baz": {
"a": 1,
"c": ["a","b","c","null",32]
},
"biz": [1,2,3,4]
}
walk/1
will be added in a future version of jq so you'll have to add it. You can grab the definition here.
# Apply f to composite entities recursively, and to atoms
def walk(f):
. as $in
| if type == "object" then
reduce keys_unsorted as $key
( {}; . + { ($key): ($in[$key] | walk(f)) } ) | f
elif type == "array" then map( walk(f) ) | f
else f
end;
Jeff - First, using walk, you can just write: walk( if type == "object" then with_entries( select(.value != null) ) elif type == "array" then map(select(. != null)) else . end). Second, walk/1 is already available in the development version.
– peak
Sep 15 '16 at 1:29
Ah, you're right, I didn't realize it went depth first. Thanks.
– Jeff Mercado
Sep 15 '16 at 2:38
add a comment |
[WARNING: the response below has several problems, not least those arising from the fact that 0|length
is 0.]
Elaborating on an earlier answer, in addition to removing properties with null
values, it's often helpful to remove JSON properties with empty array or object values (i.e., or
{}
), too.
ℹ️ — jq's
walk()
function (walk/1
) makes this easy.walk()
will be
available in a future version of jq (>jq-1.5
), but its
definition
can be added to current filters.
The condition to pass to walk()
for removing nulls and empty structures is:
walk(
if type == "object" then with_entries(select(.value|length > 0))
elif type == "array" then map(select(length > 0))
else .
end
)
Given this JSON input:
{
"notNullA": "notNullA",
"nullA": null,
"objectA": {
"notNullB": "notNullB",
"nullB": null,
"objectB": {
"notNullC": "notNullC",
"nullC": null
},
"emptyObjectB": {},
"arrayB": [
"b"
],
"emptyBrrayB":
},
"emptyObjectA": {},
"arrayA": [
"a"
],
"emptyArrayA":
}
Using this function gives the result:
{
"notNullA": "notNullA",
"objectA": {
"notNullB": "notNullB",
"objectB": {
"notNullC": "notNullC"
},
"arrayB": [
"b"
]
},
"arrayA": [
"a"
]
}
add a comment |
Elsewhere on this page, some interest has been expressed in
using jq to eliminate recursively occurrences of and {} as well as null.
Although it is possible to use the built-in definition of walk/1
to do
this, it is a bit tricky to do so correctly. Here therefore is a variant version
of walk/1
which makes it trivial to do so:
def traverse(f):
if type == "object" then map_values(traverse(f)) | f
elif type == "array" then map( traverse(f) ) | f
else f
end;
In order to make it easy to modify the criterion for removing elements,
we define:
def isempty: .==null or ((type|(.=="array" or .=="object")) and length==0);
The solution is now simply:
traverse(select(isempty|not))
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f39500608%2fremove-all-null-values%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
The following illustrates how to remove all the null-valued keys from a JSON object:
jq -n '{"a":1, "b": null, "c": null} | with_entries( select( .value != null ) )'
{
"a": 1
}
Alternatively, paths/0
can be used as follows:
. as $o | [paths | {(.) : ($o[.])} ] | add
By the way, del/1
can also be used to achieve the same result, e.g. using this filter:
reduce keys as $k (.; if .[$k] == null then del(.[$k]) else . end)
Or less obviously, but more succinctly:
del( .[ (keys - [paths]) ] )
And for the record, here are two ways to use delpaths/1
:
jq -n '{"a":1, "b": null, "c": null, "d":2} as $o
| $o
| delpaths( [ keys | select( $o[.] == null ) ] | map( [.]) )'
$ jq -n '{"a":1, "b": null, "c": null, "d":2}
| [delpaths((keys - paths) | map([.])) ] | add'
In both these last two cases, the output is the same:
{
"a": 1,
"d": 2
}
What is meant by/1
in the references to functions likedel/1
? I've seen it in other answers here, too, but not in jq's documentation.
– L S
Aug 1 '17 at 13:24
1
It is the arity of the function. The most recent versions of jq have a builtin namedbuiltins
which emits an array of strings of the form FUNCTOR/ARITY
– peak
Aug 1 '17 at 13:49
add a comment |
The following illustrates how to remove all the null-valued keys from a JSON object:
jq -n '{"a":1, "b": null, "c": null} | with_entries( select( .value != null ) )'
{
"a": 1
}
Alternatively, paths/0
can be used as follows:
. as $o | [paths | {(.) : ($o[.])} ] | add
By the way, del/1
can also be used to achieve the same result, e.g. using this filter:
reduce keys as $k (.; if .[$k] == null then del(.[$k]) else . end)
Or less obviously, but more succinctly:
del( .[ (keys - [paths]) ] )
And for the record, here are two ways to use delpaths/1
:
jq -n '{"a":1, "b": null, "c": null, "d":2} as $o
| $o
| delpaths( [ keys | select( $o[.] == null ) ] | map( [.]) )'
$ jq -n '{"a":1, "b": null, "c": null, "d":2}
| [delpaths((keys - paths) | map([.])) ] | add'
In both these last two cases, the output is the same:
{
"a": 1,
"d": 2
}
What is meant by/1
in the references to functions likedel/1
? I've seen it in other answers here, too, but not in jq's documentation.
– L S
Aug 1 '17 at 13:24
1
It is the arity of the function. The most recent versions of jq have a builtin namedbuiltins
which emits an array of strings of the form FUNCTOR/ARITY
– peak
Aug 1 '17 at 13:49
add a comment |
The following illustrates how to remove all the null-valued keys from a JSON object:
jq -n '{"a":1, "b": null, "c": null} | with_entries( select( .value != null ) )'
{
"a": 1
}
Alternatively, paths/0
can be used as follows:
. as $o | [paths | {(.) : ($o[.])} ] | add
By the way, del/1
can also be used to achieve the same result, e.g. using this filter:
reduce keys as $k (.; if .[$k] == null then del(.[$k]) else . end)
Or less obviously, but more succinctly:
del( .[ (keys - [paths]) ] )
And for the record, here are two ways to use delpaths/1
:
jq -n '{"a":1, "b": null, "c": null, "d":2} as $o
| $o
| delpaths( [ keys | select( $o[.] == null ) ] | map( [.]) )'
$ jq -n '{"a":1, "b": null, "c": null, "d":2}
| [delpaths((keys - paths) | map([.])) ] | add'
In both these last two cases, the output is the same:
{
"a": 1,
"d": 2
}
The following illustrates how to remove all the null-valued keys from a JSON object:
jq -n '{"a":1, "b": null, "c": null} | with_entries( select( .value != null ) )'
{
"a": 1
}
Alternatively, paths/0
can be used as follows:
. as $o | [paths | {(.) : ($o[.])} ] | add
By the way, del/1
can also be used to achieve the same result, e.g. using this filter:
reduce keys as $k (.; if .[$k] == null then del(.[$k]) else . end)
Or less obviously, but more succinctly:
del( .[ (keys - [paths]) ] )
And for the record, here are two ways to use delpaths/1
:
jq -n '{"a":1, "b": null, "c": null, "d":2} as $o
| $o
| delpaths( [ keys | select( $o[.] == null ) ] | map( [.]) )'
$ jq -n '{"a":1, "b": null, "c": null, "d":2}
| [delpaths((keys - paths) | map([.])) ] | add'
In both these last two cases, the output is the same:
{
"a": 1,
"d": 2
}
edited Sep 17 '16 at 4:00
answered Sep 14 '16 at 23:14
peak
30k83956
30k83956
What is meant by/1
in the references to functions likedel/1
? I've seen it in other answers here, too, but not in jq's documentation.
– L S
Aug 1 '17 at 13:24
1
It is the arity of the function. The most recent versions of jq have a builtin namedbuiltins
which emits an array of strings of the form FUNCTOR/ARITY
– peak
Aug 1 '17 at 13:49
add a comment |
What is meant by/1
in the references to functions likedel/1
? I've seen it in other answers here, too, but not in jq's documentation.
– L S
Aug 1 '17 at 13:24
1
It is the arity of the function. The most recent versions of jq have a builtin namedbuiltins
which emits an array of strings of the form FUNCTOR/ARITY
– peak
Aug 1 '17 at 13:49
What is meant by
/1
in the references to functions like del/1
? I've seen it in other answers here, too, but not in jq's documentation.– L S
Aug 1 '17 at 13:24
What is meant by
/1
in the references to functions like del/1
? I've seen it in other answers here, too, but not in jq's documentation.– L S
Aug 1 '17 at 13:24
1
1
It is the arity of the function. The most recent versions of jq have a builtin named
builtins
which emits an array of strings of the form FUNCTOR/ARITY– peak
Aug 1 '17 at 13:49
It is the arity of the function. The most recent versions of jq have a builtin named
builtins
which emits an array of strings of the form FUNCTOR/ARITY– peak
Aug 1 '17 at 13:49
add a comment |
[WARNING: the definition of walk/1
given in this response is problematic, not least for the reason given in the first comment; note also that jq 1.6 defines walk/1
differently.]
I am adding the new answer to emphasize the extended version of the script by @jeff-mercado. My version of the script assumes the empty values are as follows:
null
;
- empty arrays;
{}
- empty objects.
Removing of empty arrays and objects was borrowed from here https://stackoverflow.com/a/26196653/3627676.
def walk(f):
. as $in |
if type == "object" then
reduce keys as $key
( {}; . + { ($key): ( $in[$key] | walk(f) ) } ) | f
elif type == "array" then
select(length > 0) | map( walk(f) ) | f
else
f
end;
walk(
if type == "object" then
with_entries(select( .value != null and .value != {} and .value != ))
elif type == "array" then
map(select( . != null and . != {} and .!= ))
else
.
end
)
1
Addingselect(length > 0) |
todef walk(f)
is a mistake. For some JSON, it removes non-empty arrays. For other JSON (e.g., nested objects, each including some nulls and empty structures), only{}
was returned. However, the condition shown here works with the original definition ofwalk
. I just noticed this problem, so I can't change the vote I gave yesterday.
– L S
Aug 4 '17 at 15:41
add a comment |
[WARNING: the definition of walk/1
given in this response is problematic, not least for the reason given in the first comment; note also that jq 1.6 defines walk/1
differently.]
I am adding the new answer to emphasize the extended version of the script by @jeff-mercado. My version of the script assumes the empty values are as follows:
null
;
- empty arrays;
{}
- empty objects.
Removing of empty arrays and objects was borrowed from here https://stackoverflow.com/a/26196653/3627676.
def walk(f):
. as $in |
if type == "object" then
reduce keys as $key
( {}; . + { ($key): ( $in[$key] | walk(f) ) } ) | f
elif type == "array" then
select(length > 0) | map( walk(f) ) | f
else
f
end;
walk(
if type == "object" then
with_entries(select( .value != null and .value != {} and .value != ))
elif type == "array" then
map(select( . != null and . != {} and .!= ))
else
.
end
)
1
Addingselect(length > 0) |
todef walk(f)
is a mistake. For some JSON, it removes non-empty arrays. For other JSON (e.g., nested objects, each including some nulls and empty structures), only{}
was returned. However, the condition shown here works with the original definition ofwalk
. I just noticed this problem, so I can't change the vote I gave yesterday.
– L S
Aug 4 '17 at 15:41
add a comment |
[WARNING: the definition of walk/1
given in this response is problematic, not least for the reason given in the first comment; note also that jq 1.6 defines walk/1
differently.]
I am adding the new answer to emphasize the extended version of the script by @jeff-mercado. My version of the script assumes the empty values are as follows:
null
;
- empty arrays;
{}
- empty objects.
Removing of empty arrays and objects was borrowed from here https://stackoverflow.com/a/26196653/3627676.
def walk(f):
. as $in |
if type == "object" then
reduce keys as $key
( {}; . + { ($key): ( $in[$key] | walk(f) ) } ) | f
elif type == "array" then
select(length > 0) | map( walk(f) ) | f
else
f
end;
walk(
if type == "object" then
with_entries(select( .value != null and .value != {} and .value != ))
elif type == "array" then
map(select( . != null and . != {} and .!= ))
else
.
end
)
[WARNING: the definition of walk/1
given in this response is problematic, not least for the reason given in the first comment; note also that jq 1.6 defines walk/1
differently.]
I am adding the new answer to emphasize the extended version of the script by @jeff-mercado. My version of the script assumes the empty values are as follows:
null
;
- empty arrays;
{}
- empty objects.
Removing of empty arrays and objects was borrowed from here https://stackoverflow.com/a/26196653/3627676.
def walk(f):
. as $in |
if type == "object" then
reduce keys as $key
( {}; . + { ($key): ( $in[$key] | walk(f) ) } ) | f
elif type == "array" then
select(length > 0) | map( walk(f) ) | f
else
f
end;
walk(
if type == "object" then
with_entries(select( .value != null and .value != {} and .value != ))
elif type == "array" then
map(select( . != null and . != {} and .!= ))
else
.
end
)
edited Nov 19 at 23:48
peak
30k83956
30k83956
answered Dec 15 '16 at 18:53
jsxt
817717
817717
1
Addingselect(length > 0) |
todef walk(f)
is a mistake. For some JSON, it removes non-empty arrays. For other JSON (e.g., nested objects, each including some nulls and empty structures), only{}
was returned. However, the condition shown here works with the original definition ofwalk
. I just noticed this problem, so I can't change the vote I gave yesterday.
– L S
Aug 4 '17 at 15:41
add a comment |
1
Addingselect(length > 0) |
todef walk(f)
is a mistake. For some JSON, it removes non-empty arrays. For other JSON (e.g., nested objects, each including some nulls and empty structures), only{}
was returned. However, the condition shown here works with the original definition ofwalk
. I just noticed this problem, so I can't change the vote I gave yesterday.
– L S
Aug 4 '17 at 15:41
1
1
Adding
select(length > 0) |
to def walk(f)
is a mistake. For some JSON, it removes non-empty arrays. For other JSON (e.g., nested objects, each including some nulls and empty structures), only {}
was returned. However, the condition shown here works with the original definition of walk
. I just noticed this problem, so I can't change the vote I gave yesterday.– L S
Aug 4 '17 at 15:41
Adding
select(length > 0) |
to def walk(f)
is a mistake. For some JSON, it removes non-empty arrays. For other JSON (e.g., nested objects, each including some nulls and empty structures), only {}
was returned. However, the condition shown here works with the original definition of walk
. I just noticed this problem, so I can't change the vote I gave yesterday.– L S
Aug 4 '17 at 15:41
add a comment |
That's not what del/1
was meant to be used for. Given an object as input, if you wanted to remove the .phones
property, you'd do:
del(.phones)
In other words, the parameter to del
is the path to the property you wish to remove.
If you wanted to use this, you would have to figure out all the paths to null
values and pass it in to this. That would be more of a hassle though.
For an easier approach, you'll have to walk through the object tree to find null
values. If found, remove the corresponding property (or otherwise filter it out). Using walk/1
, your filter could be applied recursively to exclude the null
values.
walk(
if type == "object" then
with_entries(select(.value != null))
elif type == "array" then
map(select(. != null))
else
.
end
)
So if you had this for input:
{
"foo": null,
"bar": "bar",
"biz": [1,2,3,4,null],
"baz": {
"a": 1,
"b": null,
"c": ["a","b","c","null",32,null]
}
}
This filter would yield:
{
"bar": "bar",
"baz": {
"a": 1,
"c": ["a","b","c","null",32]
},
"biz": [1,2,3,4]
}
walk/1
will be added in a future version of jq so you'll have to add it. You can grab the definition here.
# Apply f to composite entities recursively, and to atoms
def walk(f):
. as $in
| if type == "object" then
reduce keys_unsorted as $key
( {}; . + { ($key): ($in[$key] | walk(f)) } ) | f
elif type == "array" then map( walk(f) ) | f
else f
end;
Jeff - First, using walk, you can just write: walk( if type == "object" then with_entries( select(.value != null) ) elif type == "array" then map(select(. != null)) else . end). Second, walk/1 is already available in the development version.
– peak
Sep 15 '16 at 1:29
Ah, you're right, I didn't realize it went depth first. Thanks.
– Jeff Mercado
Sep 15 '16 at 2:38
add a comment |
That's not what del/1
was meant to be used for. Given an object as input, if you wanted to remove the .phones
property, you'd do:
del(.phones)
In other words, the parameter to del
is the path to the property you wish to remove.
If you wanted to use this, you would have to figure out all the paths to null
values and pass it in to this. That would be more of a hassle though.
For an easier approach, you'll have to walk through the object tree to find null
values. If found, remove the corresponding property (or otherwise filter it out). Using walk/1
, your filter could be applied recursively to exclude the null
values.
walk(
if type == "object" then
with_entries(select(.value != null))
elif type == "array" then
map(select(. != null))
else
.
end
)
So if you had this for input:
{
"foo": null,
"bar": "bar",
"biz": [1,2,3,4,null],
"baz": {
"a": 1,
"b": null,
"c": ["a","b","c","null",32,null]
}
}
This filter would yield:
{
"bar": "bar",
"baz": {
"a": 1,
"c": ["a","b","c","null",32]
},
"biz": [1,2,3,4]
}
walk/1
will be added in a future version of jq so you'll have to add it. You can grab the definition here.
# Apply f to composite entities recursively, and to atoms
def walk(f):
. as $in
| if type == "object" then
reduce keys_unsorted as $key
( {}; . + { ($key): ($in[$key] | walk(f)) } ) | f
elif type == "array" then map( walk(f) ) | f
else f
end;
Jeff - First, using walk, you can just write: walk( if type == "object" then with_entries( select(.value != null) ) elif type == "array" then map(select(. != null)) else . end). Second, walk/1 is already available in the development version.
– peak
Sep 15 '16 at 1:29
Ah, you're right, I didn't realize it went depth first. Thanks.
– Jeff Mercado
Sep 15 '16 at 2:38
add a comment |
That's not what del/1
was meant to be used for. Given an object as input, if you wanted to remove the .phones
property, you'd do:
del(.phones)
In other words, the parameter to del
is the path to the property you wish to remove.
If you wanted to use this, you would have to figure out all the paths to null
values and pass it in to this. That would be more of a hassle though.
For an easier approach, you'll have to walk through the object tree to find null
values. If found, remove the corresponding property (or otherwise filter it out). Using walk/1
, your filter could be applied recursively to exclude the null
values.
walk(
if type == "object" then
with_entries(select(.value != null))
elif type == "array" then
map(select(. != null))
else
.
end
)
So if you had this for input:
{
"foo": null,
"bar": "bar",
"biz": [1,2,3,4,null],
"baz": {
"a": 1,
"b": null,
"c": ["a","b","c","null",32,null]
}
}
This filter would yield:
{
"bar": "bar",
"baz": {
"a": 1,
"c": ["a","b","c","null",32]
},
"biz": [1,2,3,4]
}
walk/1
will be added in a future version of jq so you'll have to add it. You can grab the definition here.
# Apply f to composite entities recursively, and to atoms
def walk(f):
. as $in
| if type == "object" then
reduce keys_unsorted as $key
( {}; . + { ($key): ($in[$key] | walk(f)) } ) | f
elif type == "array" then map( walk(f) ) | f
else f
end;
That's not what del/1
was meant to be used for. Given an object as input, if you wanted to remove the .phones
property, you'd do:
del(.phones)
In other words, the parameter to del
is the path to the property you wish to remove.
If you wanted to use this, you would have to figure out all the paths to null
values and pass it in to this. That would be more of a hassle though.
For an easier approach, you'll have to walk through the object tree to find null
values. If found, remove the corresponding property (or otherwise filter it out). Using walk/1
, your filter could be applied recursively to exclude the null
values.
walk(
if type == "object" then
with_entries(select(.value != null))
elif type == "array" then
map(select(. != null))
else
.
end
)
So if you had this for input:
{
"foo": null,
"bar": "bar",
"biz": [1,2,3,4,null],
"baz": {
"a": 1,
"b": null,
"c": ["a","b","c","null",32,null]
}
}
This filter would yield:
{
"bar": "bar",
"baz": {
"a": 1,
"c": ["a","b","c","null",32]
},
"biz": [1,2,3,4]
}
walk/1
will be added in a future version of jq so you'll have to add it. You can grab the definition here.
# Apply f to composite entities recursively, and to atoms
def walk(f):
. as $in
| if type == "object" then
reduce keys_unsorted as $key
( {}; . + { ($key): ($in[$key] | walk(f)) } ) | f
elif type == "array" then map( walk(f) ) | f
else f
end;
edited Nov 19 at 23:52
peak
30k83956
30k83956
answered Sep 14 '16 at 23:29
Jeff Mercado
90.6k18183211
90.6k18183211
Jeff - First, using walk, you can just write: walk( if type == "object" then with_entries( select(.value != null) ) elif type == "array" then map(select(. != null)) else . end). Second, walk/1 is already available in the development version.
– peak
Sep 15 '16 at 1:29
Ah, you're right, I didn't realize it went depth first. Thanks.
– Jeff Mercado
Sep 15 '16 at 2:38
add a comment |
Jeff - First, using walk, you can just write: walk( if type == "object" then with_entries( select(.value != null) ) elif type == "array" then map(select(. != null)) else . end). Second, walk/1 is already available in the development version.
– peak
Sep 15 '16 at 1:29
Ah, you're right, I didn't realize it went depth first. Thanks.
– Jeff Mercado
Sep 15 '16 at 2:38
Jeff - First, using walk, you can just write: walk( if type == "object" then with_entries( select(.value != null) ) elif type == "array" then map(select(. != null)) else . end). Second, walk/1 is already available in the development version.
– peak
Sep 15 '16 at 1:29
Jeff - First, using walk, you can just write: walk( if type == "object" then with_entries( select(.value != null) ) elif type == "array" then map(select(. != null)) else . end). Second, walk/1 is already available in the development version.
– peak
Sep 15 '16 at 1:29
Ah, you're right, I didn't realize it went depth first. Thanks.
– Jeff Mercado
Sep 15 '16 at 2:38
Ah, you're right, I didn't realize it went depth first. Thanks.
– Jeff Mercado
Sep 15 '16 at 2:38
add a comment |
[WARNING: the response below has several problems, not least those arising from the fact that 0|length
is 0.]
Elaborating on an earlier answer, in addition to removing properties with null
values, it's often helpful to remove JSON properties with empty array or object values (i.e., or
{}
), too.
ℹ️ — jq's
walk()
function (walk/1
) makes this easy.walk()
will be
available in a future version of jq (>jq-1.5
), but its
definition
can be added to current filters.
The condition to pass to walk()
for removing nulls and empty structures is:
walk(
if type == "object" then with_entries(select(.value|length > 0))
elif type == "array" then map(select(length > 0))
else .
end
)
Given this JSON input:
{
"notNullA": "notNullA",
"nullA": null,
"objectA": {
"notNullB": "notNullB",
"nullB": null,
"objectB": {
"notNullC": "notNullC",
"nullC": null
},
"emptyObjectB": {},
"arrayB": [
"b"
],
"emptyBrrayB":
},
"emptyObjectA": {},
"arrayA": [
"a"
],
"emptyArrayA":
}
Using this function gives the result:
{
"notNullA": "notNullA",
"objectA": {
"notNullB": "notNullB",
"objectB": {
"notNullC": "notNullC"
},
"arrayB": [
"b"
]
},
"arrayA": [
"a"
]
}
add a comment |
[WARNING: the response below has several problems, not least those arising from the fact that 0|length
is 0.]
Elaborating on an earlier answer, in addition to removing properties with null
values, it's often helpful to remove JSON properties with empty array or object values (i.e., or
{}
), too.
ℹ️ — jq's
walk()
function (walk/1
) makes this easy.walk()
will be
available in a future version of jq (>jq-1.5
), but its
definition
can be added to current filters.
The condition to pass to walk()
for removing nulls and empty structures is:
walk(
if type == "object" then with_entries(select(.value|length > 0))
elif type == "array" then map(select(length > 0))
else .
end
)
Given this JSON input:
{
"notNullA": "notNullA",
"nullA": null,
"objectA": {
"notNullB": "notNullB",
"nullB": null,
"objectB": {
"notNullC": "notNullC",
"nullC": null
},
"emptyObjectB": {},
"arrayB": [
"b"
],
"emptyBrrayB":
},
"emptyObjectA": {},
"arrayA": [
"a"
],
"emptyArrayA":
}
Using this function gives the result:
{
"notNullA": "notNullA",
"objectA": {
"notNullB": "notNullB",
"objectB": {
"notNullC": "notNullC"
},
"arrayB": [
"b"
]
},
"arrayA": [
"a"
]
}
add a comment |
[WARNING: the response below has several problems, not least those arising from the fact that 0|length
is 0.]
Elaborating on an earlier answer, in addition to removing properties with null
values, it's often helpful to remove JSON properties with empty array or object values (i.e., or
{}
), too.
ℹ️ — jq's
walk()
function (walk/1
) makes this easy.walk()
will be
available in a future version of jq (>jq-1.5
), but its
definition
can be added to current filters.
The condition to pass to walk()
for removing nulls and empty structures is:
walk(
if type == "object" then with_entries(select(.value|length > 0))
elif type == "array" then map(select(length > 0))
else .
end
)
Given this JSON input:
{
"notNullA": "notNullA",
"nullA": null,
"objectA": {
"notNullB": "notNullB",
"nullB": null,
"objectB": {
"notNullC": "notNullC",
"nullC": null
},
"emptyObjectB": {},
"arrayB": [
"b"
],
"emptyBrrayB":
},
"emptyObjectA": {},
"arrayA": [
"a"
],
"emptyArrayA":
}
Using this function gives the result:
{
"notNullA": "notNullA",
"objectA": {
"notNullB": "notNullB",
"objectB": {
"notNullC": "notNullC"
},
"arrayB": [
"b"
]
},
"arrayA": [
"a"
]
}
[WARNING: the response below has several problems, not least those arising from the fact that 0|length
is 0.]
Elaborating on an earlier answer, in addition to removing properties with null
values, it's often helpful to remove JSON properties with empty array or object values (i.e., or
{}
), too.
ℹ️ — jq's
walk()
function (walk/1
) makes this easy.walk()
will be
available in a future version of jq (>jq-1.5
), but its
definition
can be added to current filters.
The condition to pass to walk()
for removing nulls and empty structures is:
walk(
if type == "object" then with_entries(select(.value|length > 0))
elif type == "array" then map(select(length > 0))
else .
end
)
Given this JSON input:
{
"notNullA": "notNullA",
"nullA": null,
"objectA": {
"notNullB": "notNullB",
"nullB": null,
"objectB": {
"notNullC": "notNullC",
"nullC": null
},
"emptyObjectB": {},
"arrayB": [
"b"
],
"emptyBrrayB":
},
"emptyObjectA": {},
"arrayA": [
"a"
],
"emptyArrayA":
}
Using this function gives the result:
{
"notNullA": "notNullA",
"objectA": {
"notNullB": "notNullB",
"objectB": {
"notNullC": "notNullC"
},
"arrayB": [
"b"
]
},
"arrayA": [
"a"
]
}
edited Nov 19 at 23:17
peak
30k83956
30k83956
answered Aug 4 '17 at 17:06
L S
1,90312138
1,90312138
add a comment |
add a comment |
Elsewhere on this page, some interest has been expressed in
using jq to eliminate recursively occurrences of and {} as well as null.
Although it is possible to use the built-in definition of walk/1
to do
this, it is a bit tricky to do so correctly. Here therefore is a variant version
of walk/1
which makes it trivial to do so:
def traverse(f):
if type == "object" then map_values(traverse(f)) | f
elif type == "array" then map( traverse(f) ) | f
else f
end;
In order to make it easy to modify the criterion for removing elements,
we define:
def isempty: .==null or ((type|(.=="array" or .=="object")) and length==0);
The solution is now simply:
traverse(select(isempty|not))
add a comment |
Elsewhere on this page, some interest has been expressed in
using jq to eliminate recursively occurrences of and {} as well as null.
Although it is possible to use the built-in definition of walk/1
to do
this, it is a bit tricky to do so correctly. Here therefore is a variant version
of walk/1
which makes it trivial to do so:
def traverse(f):
if type == "object" then map_values(traverse(f)) | f
elif type == "array" then map( traverse(f) ) | f
else f
end;
In order to make it easy to modify the criterion for removing elements,
we define:
def isempty: .==null or ((type|(.=="array" or .=="object")) and length==0);
The solution is now simply:
traverse(select(isempty|not))
add a comment |
Elsewhere on this page, some interest has been expressed in
using jq to eliminate recursively occurrences of and {} as well as null.
Although it is possible to use the built-in definition of walk/1
to do
this, it is a bit tricky to do so correctly. Here therefore is a variant version
of walk/1
which makes it trivial to do so:
def traverse(f):
if type == "object" then map_values(traverse(f)) | f
elif type == "array" then map( traverse(f) ) | f
else f
end;
In order to make it easy to modify the criterion for removing elements,
we define:
def isempty: .==null or ((type|(.=="array" or .=="object")) and length==0);
The solution is now simply:
traverse(select(isempty|not))
Elsewhere on this page, some interest has been expressed in
using jq to eliminate recursively occurrences of and {} as well as null.
Although it is possible to use the built-in definition of walk/1
to do
this, it is a bit tricky to do so correctly. Here therefore is a variant version
of walk/1
which makes it trivial to do so:
def traverse(f):
if type == "object" then map_values(traverse(f)) | f
elif type == "array" then map( traverse(f) ) | f
else f
end;
In order to make it easy to modify the criterion for removing elements,
we define:
def isempty: .==null or ((type|(.=="array" or .=="object")) and length==0);
The solution is now simply:
traverse(select(isempty|not))
edited Nov 20 at 0:06
answered Nov 19 at 23:42
peak
30k83956
30k83956
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f39500608%2fremove-all-null-values%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
Please extend this to be complete enough to run, showing input, actual output, and desired output. (For instance, you could provide minimal JSON input in a heredoc, by running
jq '...your code here...' <<'EOF'
, including some JSON that demonstrates the problem, and having anEOF
afterwards). See also the Help Center documentation on Minimal, Complete, Verifiable Examples.– Charles Duffy
Sep 14 '16 at 22:31
...as it is, it's hard to tell where in your data structure the NULs actually are, which is critical to being able to build or test a solution.
– Charles Duffy
Sep 14 '16 at 22:35
Note that while I'm voting to close the question as it's currently written, (1) it won't actually be closed unless others agree, and (2) editing a closed question automatically puts it into a queue to be considered for reopening, so extending it to include a MCVE should result in that closure being reversed.
– Charles Duffy
Sep 14 '16 at 22:37
@CharlesDuffy - Regarding your comment about "NULs" -- (1) the OP was asking about JSON "null", not "NUL"; (2) to anyone who knows jq, it's clear where the nulls are; (3) to anyone who knows JSON, it's fairly obvious.
– peak
Dec 15 '16 at 18:58
@peak, it's not obvious to me without following the github link to see the data at hand, and questions that only make sense when given out-of-band content are explicitly incomplete here -- that's extremely well-settled on meta, hence, my request for actual input to be included in the question itself. Yes, one could also edit the input data into the question itself -- either of us does that and there's no more grounds for disagreement. That said, asking the OP to do so themselves has the benefit of making it less likely they'll make the same mistake again in the future.
– Charles Duffy
Dec 15 '16 at 20:53