1

I have many JSON objects, which look like below, and what I would like to do, is transform each object, where apart from the small adjustments, the node named last, adds the length nodes, so as in the end, we have the sum of lengths, for each part:

Input sample JSON object

{ 
    "serialnumber": "5690",
    "duplicate": true,
    "parts": [
        {
            "serialnumber": "43",
            "position_in": true,
            "duplicate": true,
            "positions": [
                {
                    "self": 0,
                    "length": 3
                },
                {
                    "self": 4,
                    "length": 1
                },
                {
                    "self": 5,
                    "length": 2
                }
            ]
        },
        {
            "serialnumber": "745",
            "position_in": true,
            "duplicate": false,
            "positions": [
                {
                    "self": 0,
                    "length": 8
                },
                {
                    "self": 8,
                    "length": 1
                },
                {
                    "self": 9,
                    "length": 1
                }
            ]
        }
    ]
}

Desired JSON output:

{
    "5690": {
        "duplicate": true,
        "parts": {
            "43": {
                "position_in": true,
                "duplicate": true,
                "last": "7"
            },
            "745": {
                "position_in": true,
                "duplicate": false,
                "last": "10"
            }
        }
    }
}

How would you achieve the desired result, using jq, and the + operator?

1 Answer 1

1

The trick here is to define a helper function:

# Given a part, extract the desired bits and the sum of the lengths:
def part: 
  { (.serialnumber):
      {position_in,
       duplicate,
       last: (.positions | map(.length) | add) }};

Now we can essentially write down what we want declaratively:

{ (.serialnumber): { duplicate, "parts": (.parts | map(part) ) } }

Output

With your data in sample.json, and the above in a file named program.jq, the invocation:

 jq -f program.jq sample.json

produces:

{
  "5690": {
    "duplicate": true,
    "parts": [
      {
        "43": {
          "position_in": true,
          "duplicate": true,
          "last": 6
        }
      },
      {
        "745": {
          "position_in": true,
          "duplicate": false,
          "last": 10
        }
      }
    ]
  }
}
Sign up to request clarification or add additional context in comments.

5 Comments

how should the above be made, in order to be able to iterate over all objects of the sample JSON file? I have an array, of objects like the one above, in the sample JSON file
[ {...like_sample_JSON_file}, {...like_sample_JSON_file}, {...like_sample_JSON_file}, {...like_sample_JSON_file},], so i need to iterate to each object, and .[] that i used did not help me
It depends on whether you want the final result to be an array or a stream. You could use map(_) for the former, and .[] | _ for the latter, but there are other alternatives in each case. You might want to look at one of the jq tutorials....
an example with the final result to be an array, would be welcome, in your above answer, thank you
So wrap map around the single-line part of the program: map( ... )

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.