Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modify object properties conditionally with jq

I have this sample of JSON:

[
    {
        "name": "val1",
        "expire": { "$value": 10 }
    },
    {
        "name": "val2",
        "expire": 20
    },
    {
        "name": "val3"
    }
]

And I want to transform it to this form with jq:

[
    {
        "name": "val1",
        "expire": 10
    },
    {
        "name": "val2",
        "expire": 20
    },
    {
        "name": "val3",
        "expire": null
    }
]

All that I've found it's if-then-else, but it looks like I have no clue how to build right expression.

Condition based on type check, it looks like a right way, but just return "compile"-time error, I don't know how to fix it:

.[] | { name, expire: (if .expire then (if type(.expire) == "number" then .expire else .expire."$value" end) else null end) }

Condition based on "$value" check, somehow filter out second object:

.[] | { name, expire: (if .expire then (if .expire."$value"? then .expire."$value" else .expire end) else null end) }

As I understand, the problem here in internal if, where second object checked with .expire."$value"?, error was thrown and object removed from result because of error.

like image 494
dr.tyrion Avatar asked Sep 04 '16 19:09

dr.tyrion


2 Answers

Try this filter:

map( {name, 
      "expire": (.expire | if type == "object" then .["$value"] elif type == "number" then . else null end) } )

or (with significantly different semantics in edge cases):

map(.expire |= if type == "object" then .["$value"]
               elif type == "number" then . else null end)
like image 112
peak Avatar answered Nov 16 '22 03:11

peak


You can think of it another way as updating each object's expire property with the "$value" if present, or the current value. If the value doesn't exist, it's just simply null.

.[].expire |= (."$value"? // .)
like image 40
Jeff Mercado Avatar answered Nov 16 '22 03:11

Jeff Mercado