2

Using the example on the jmesPath home page, given this JSON:

{
  "locations": [
    {"name": "Seattle", "state": "WA"},
    {"name": "New York", "state": "NY"},
    {"name": "Bellevue", "state": "WA"},
    {"name": "Olympia", "state": "WA"}
  ]
}

I want to transform select values in the JSON, and otherwise return the JSON intact. For example, suppose I wanted to move the city of New York to the state of Hawaii, and move Seattle to New Mexico. The result would be:

{
  "locations": [
    {"name": "Seattle", "state": "NM"},
    {"name": "New York", "state": "HI"},
    {"name": "Bellevue", "state": "WA"},
    {"name": "Olympia", "state": "WA"}
  ]
}

If I were doing this in JavaScript, what I want to do would be something like this:

let object = JSON.parse( raw_json );
object.locations[0].state = "NM";
object.locations[1].state = "HI";
raw_json = JSON.stringify( object );

The trick is, I don't want to have to embed more knowledge about the structure of the JSON than is necessary to be able to perform my transformations, that way if the parts of the JSON that I'm not modifying were to change, the expression still works as intended. Ideally, I would use an expression in place of hard-coded array offsets. But I left that out of the JavaScript code, for brevity.

Does jmesPath support this use case? If so, what is the syntax?

John Arrowwood
  • 2,370
  • 2
  • 21
  • 32
  • If I understand right you want to have ` {"name": "New York", "state": "NY"} ` and ` {"name": "Seattle", "state": "WA"} ` embed in your new json ? like this: { "locations": [ {"name": "Seattle", "state": "NM"}, {"name": "New York", "state": "HI"}, {"name": "Bellevue", "state": "WA"}, {"name": "Olympia", "state": "WA"}, {"name": "New York", "state": "NY"}, {"name": "Seattle", "state": "WA"} ] } – bosskay972 Sep 11 '19 at 00:40
  • I want the output of the expression to be exactly what is shown in the second code block, same as would be the output of the sample javascript code (3rd block), which illustrates the logic I'm trying to accomplish. – John Arrowwood Sep 11 '19 at 20:26
  • I don't think you can change information in JMESPath the only way toi change something(I think) is to use "merge" function, I do a query but it's handmade and dirty for me there is no dynamical solution to your problem, here's my query: `[locations[0].merge(@,{name: 'Seattle', state: 'NM'}),locations[1].merge(@,{name: 'New York', state: 'HI'}),locations[2],locations[3]]` – bosskay972 Sep 11 '19 at 20:43

1 Answers1

1

You need to use an iterative approach and in each iteration handle a specific city. Also, you can use merge function to persist existing info under each location items.

Below is a sample for two iteration. You can easily expand the results for the more cities.

{ "locations": [
                  // lines below replace states for cities of Seattle and New York.
                merge( locations[? name == 'Seattle' ] | [0] , {state: 'NM'}),
                merge( locations[? name == 'New York' ] | [0] , {state: 'HI'}),
                  // this line includes other cities as they are
                locations[? ! contains( ['Seattle', 'New York'], name) ],
                  // use the flatten operator to order all locations at the same level
               ][]
 }
PyGuy
  • 434
  • 5
  • 15