0

Let's say I have a JSON file recipe.json containing this:

{
            "name": "Curried Lentils and Rice",
            "ingredients": [
                {
                    "quantity": "1 quart",
                    "name": "beef broth",
                    "type": "Misc"
                },
                {
                    "quantity": "1 cup",
                    "name": "dried green lentils",
                    "type": "Misc"
                },
                {
                    "quantity": "1/2 cup",
                    "name": "basmati rice",
                    "type": "Misc"
                },
                {
                    "quantity": "1 tsp",
                    "name": "curry powder",
                    "type": "Condiments"
                },
                {
                    "quantity": "1 tsp",
                    "name": "salt",
                    "type": "Condiments"
                }
            ],
            "steps": [
                "Bring broth to a low boil.",
                "Add curry powder and salt.",
                "Cook lentils for 20 minutes.",
                "Add rice and simmer for 20 minutes.",
                "Enjoy!"
            ],
            "timers": [
                0,
                0,
                20,
                20,
                0
            ],
            "imageURL": "http://dagzhsfg97k4.cloudfront.net/wp-content/uploads/2012/05/lentils3.jpg"
}

And I'm trying to insert new JSON fields into the file at specific positions in the file, using jq such as:

"cuisine": "meditaranean"

will become the 2nd entry, and

"meal": "lunch"

will become the 4th entry. So the file after the command is like this:

{
            "name": "Curried Lentils and Rice",
            "cuisine": "meditaranean"
            "ingredients": [
                {
                    "quantity": "1 quart",
                    "name": "beef broth",
                    "type": "Misc"
                },
                {
                    "quantity": "1 cup",
                    "name": "dried green lentils",
                    "type": "Misc"
                },
                {
                    "quantity": "1/2 cup",
                    "name": "basmati rice",
                    "type": "Misc"
                },
                {
                    "quantity": "1 tsp",
                    "name": "curry powder",
                    "type": "Condiments"
                },
                {
                    "quantity": "1 tsp",
                    "name": "salt",
                    "type": "Condiments"
                }
            ],
            "meal": "lunch"
            "steps": [
                "Bring broth to a low boil.",
                "Add curry powder and salt.",
                "Cook lentils for 20 minutes.",
                "Add rice and simmer for 20 minutes.",
                "Enjoy!"
            ],
            "timers": [
                0,
                0,
                20,
                20,
                0
            ],
            "imageURL": "http://dagzhsfg97k4.cloudfront.net/wp-content/uploads/2012/05/lentils3.jpg"
}

My question is how to do this with jq?

Note: This other question addresses performing updates of single fields, while the current question is about inserts. They are as different as orange and yellow bell peppers, which is different! (Don't make me add a picture of bell peppers to this post, I swear I'll do it if I have to.)

ted.strauss
  • 4,119
  • 4
  • 34
  • 57
  • 2
    Possible duplicate of [How do I update a single value in a json document using jq?](https://stackoverflow.com/questions/31034746/how-do-i-update-a-single-value-in-a-json-document-using-jq) – Jeff Mercado Jun 06 '18 at 22:31
  • 1
    @JeffMercado - Methinks that is a different Q. This one asks for the *addition* of a key/value pair at a specific spot. – peak Jun 06 '18 at 23:03
  • Inserting and updating via jq is the same. If the element doesnt exist, it will create it. – jonypony3 Apr 23 '19 at 20:38

2 Answers2

0

With the help of a helper function, the task becomes trivial:

def insert_kv($key; $value; $ix):
  to_entries
  | .[0:$ix] + [{key: $key, value: $value}] + .[$ix:]
  | from_entries;

insert_kv("cuisine"; "mediterranean"; 1)
| insert_kv("meal"; "lunch"; 3)

You could (alternatively or in addition) define:

def insert_kv($object; $ix):
  to_entries
  | .[0:$ix] + ($object|to_entries) + .[$ix:]
  | from_entries;
peak
  • 105,803
  • 17
  • 152
  • 177
  • what are `to_entries` and `from_entries` supposed to be here? is that a whole jq expression? – ted.strauss Jun 12 '18 at 19:31
  • They are "well-known" builtin filters, and are documented in the jq manual: https://stedolan.github.io/jq/manual/ . (One could alternatively use `with_entries/1` here.) – peak Jun 12 '18 at 19:39
  • jq has an crud operations built in, why would you not use them? – jonypony3 Apr 23 '19 at 20:42
  • @jonypony3 - which crud operation for inserting at a specific position do you have in mind? – peak Apr 23 '19 at 22:12
0

Where your json is saved to meals.json, executing the following command will result into exactly what you need.

jq '.cusine="mediteranean"' meals.json
jonypony3
  • 410
  • 2
  • 19