Karate: enhancement: merge two json objects

Created on 14 May 2019  路  6Comments  路  Source: intuit/karate

As offered here: https://stackoverflow.com/questions/50580415/karate-array-field-become-object
by @ptrthomas
Maybe we need a karate.append() and karate.merge() (for merging 2 JSON objects). Feel free to raise a feature request.

I would love to see a merge function. I have data driven tests where not all assertions in the test data files are mandatory, and I'd like to merge a "default" json with them, allowing the values in the file to override these defaults.

enhancement fixed

Most helpful comment

@thunderstumpges done

Scenario: merge
    * def foo = { a: 1 }
    * def bar = karate.merge(foo, { b: 2 })
    * match bar == { a: 1, b: 2 }

Scenario: append
    * def foo = [{ a: 1 }]
    * def bar = karate.append(foo, { b: 2 })
    * match bar == [{ a: 1 }, { b: 2 }]

All 6 comments

@thunderstumpges done

Scenario: merge
    * def foo = { a: 1 }
    * def bar = karate.merge(foo, { b: 2 })
    * match bar == { a: 1, b: 2 }

Scenario: append
    * def foo = [{ a: 1 }]
    * def bar = karate.append(foo, { b: 2 })
    * match bar == [{ a: 1 }, { b: 2 }]

@thunderstumpges I hope you are aware of the contains keyword, because that's what most teams use when they don't care about all the fields. you can get even fancier with "fuzzy matching": https://github.com/intuit/karate#fuzzy-matching

Wow, thanks! That has GOT to be the fastest turnaround on a feature request ever! :)

Yes I have looked at contains and fuzzy matching. I actually do use fuzzy matching in a number of places.
I ran into friction with contains, as the parts being asserted in the response are nested in fairly complex ways, and I didn't want the test writers to have to replicate that nesting in their test data. I did also look into karate.map but with the "optional-ness" of the assertions, I didn't see how to "optionally map" into the response structure.

I do have a working solution in place, and I think the above will help even more with this, so Thanks!

But for those curious, below is an example of my scenario. Test writers fill in test data in yaml files which drive the tests:

Test Yaml:

- input: some text
  response: '#regex ^response assertion$'
  maybeMatchString: match if specified in test
  maybeMatchArray: 
  - name: xxx
    value: yyy
- input: another test
  response: '#regex ^another response assertion$'
  # note, no optional match data, so don't assert on it

And when matching to the response, the nesting is more complex:
```json
{
"innerResponse": {
"otherInnerObject" : {
"textToMatchResponse" : "response value"
}
},
"anotherMaybeObject" : {
"nested" : {
"maybeMatchString" : "match this if it was in the test"
},
"maybeMatchArray" : [
{
"name" : "match this if it was in the test",
"value" : "same"
}
]
}

@thunderstumpges okay, I probably don't yet understand the yaml part - but do blog about this or something, it sounds interesting. one more suggestion is that when dealing with complex nesting, JsonPath can be useful:

* def response =
"""
{
  "innerResponse": {
    "otherInnerObject": {
      "textToMatchResponse": "response value"
    }
  },
  "anotherMaybeObject": {
    "nested": {
      "maybeMatchString": "match this if it was in the test"
    },
    "maybeMatchArray": [
      {
        "name": "match this if it was in the test",
        "value": "same"
      }
    ]
  }
}
"""
* def inner = $response..otherInnerObject
* match inner contains { textToMatchResponse: 'response value' }

Thanks, yes good idea!

released 0.9.3

Was this page helpful?
0 / 5 - 0 ratings