I have JSONObject instance which contains some property,
{
"name":"testName",
"age":"23"
}
i use the following assert, but it fails. Is this correct approach to test JSON in assertj.
assertThat(jsonObject).hasFieldOrProperty("name");
If you want to do any serious assertions on JSON object, I would recommend JsonUnit https://github.com/lukas-krecan/JsonUnit
I think it has to do with the fact the JSONObject is like a map which has key-value pairs, while AssertJ expects Java bean-style objects to check if a property exists. I understood this from the document at https://joel-costigliola.github.io/assertj/core/api/org/assertj/core/api/AbstractObjectAssert.html#hasFieldOrProperty(java.lang.String). Hope I am looking at the right place.
I mean to say that a map or JSONObject doesn't have fields declared in it for AssertJ to look for.
You may use JSONObject.has( String key ) instead, I think.
If you use SpringBoot you can use the custom impl. for Assertj
private final BasicJsonTester json = new BasicJsonTester(getClass());
#Test
void testIfHasPropertyName() {
final JSONObject jsonObject = new JSONObject("{\n" +
"\"name\":\"testName\",\n" +
"\"age\":\"23\"\n" +
"}");
assertThat(json.from(jsonObject.toString())).hasJsonPath( "$.name");
}
Fist, you need to traverse the keysets (nodes) using the map class, then verify if the keyset contains the particular node you are looking for.
Map<String, Object> read = JsonPath.read(JSONObject, "$");
assertThat(read.keySet()).contains("name");
Related
For example, I have JSON in response:
[{"id":1,"name":"text"},{"id":2,"name":"text"}]}
I want to verify if a response contains a custom object. For example:
Person(id=1, name=text)
I found solution:
Person[] persons = response.as(Person[].class);
assertThat(person, IsArrayContaining.hasItemInArray(expectedPerson));
I want to have something like this:
response.then().assertThat().body(IsArrayContaining.hasItemInArray(object));
Is there any solution for this?
Thanks in advance for your help!
The body() method accepts a path and a Hamcrest matcher (see the javadocs).
So, you could do this:
response.then().assertThat().body("$", customMatcher);
For example:
// 'expected' is the serialised form of your Person
// this is a crude way of creating that serialised form
// you'll probably use whatever JSON de/serialisaiotn library is in use in your project
Map<String, Object> expected = new HashMap<String, Object>();
expected.put("id", 1);
expected.put("name", "text");
response.then().assertThat().body("$", Matchers.hasItem(expected));
This works for me:
body("path.to.array",
hasItem(
allOf(
hasEntry("firstName", "test"),
hasEntry("lastName", "test")
)
)
)
In this case, you can also use json schema validation. By using this we don't need to set individual rules for JSON elements.
Have a look at Rest assured schema validation
get("/products").then().assertThat().body(matchesJsonSchemaInClasspath("products-schema.json"));
I have a code that consumes map of properties with string keys which represents some kind of context. And I want this code to fail if the map does not contain some of the required properties.
The corresponding code might look like this:
SomeResultType businessMethod(Map<String, String> context) {
Assert.isTrue(context.containsKey("A"), "A property must not be empty");
Assert.isTrue(context.containsKey("B"), "B property must not be empty");
Assert.isTrue(context.containsKey("C"), "C property must not be empty");
// ...
}
I wrote a simple replacement by myself with signature like this
public static <K, V> void mapContainsKeys(Map<K, V> map, K... keys)
But I think that something like this must be already implemented somewhere. So I'm searching for library replacement of this code.
It would be great if Spring guys implemented something like this in org.springframework.util.Assert.
if you want to just check that a map contains a list of keys, use this:
map.keySet().containsAll(keys)
if you want more details, to know which ones were missing:
Set<String> missingKeys = new HashSet<>(keys);
missingKeys.removeAll(map.keySet());
and then:
if (!missingKeys.isEmpty()) {
throw new IllegalArgumentException(missingKeys + " keys missing");
}
The fact that you had to write a helper method means that you are probably manipulating maps all over your code.
Looks like a code smell to me, you should probably map your properties to an object that you can validate once and pass everywhere.
Since you are using Spring, and if you are using Spring Boot (most people do nowadays), you can use #ConfigurationProperties to map your configuration properties to an object.
This way you can also add validation like #javax.validation.constraints.NotNull and make sure your properties are valid.
I have a json string, here is example
{
"Param1":"Value1",
"Param2":{...}
"ParamThatINeed":{...}
}
I want to get only "ParamThatINeed" object using gson lib in java, what is the best way to get what I need - write root class, then write class for "ParamThatINeed" and then decode json and use only "ParamThatINeed" object?
Or maybe it's better to beforehand convert my jsonString to another string, which will be only "ParamThatINeed" jsonString object using for example regexp? Or maybe there is a better way?
Your suggested solution is painless and extensible (i.e. if you decide to read an additional field in the future, you just add another field to your object). In general that's exactly how you want to use Gson - construct the necessary Java classes to represent the data you care about and Gson will silently discard the fields you don't care about. For your example that could look like:
private static final Gson GSON = ...;
public static class MyJsonData {
private final ParamThatINeed paramThatINeed;
public ParamThatINeed getParamThatINeed() { ... }
}
public static class ParamThatINeed {
...
}
public static ParamThatINeed extractParamThatINeed(String json) {
return GSON.fromJson(json, MyJsonData.class).getParamThatINeed();
}
You could parse the field yourself as #GuiSim suggests, but this won't scale as easily if your requirements change, and generally speaking the idea behind Gson is to avoid working directly with JsonElement and related classes.
I would definitely discourage a pre-processing step converting the JSON string into a different format. Structured data and string manipulations don't mix, as they lead to brittle code. JSON parsing libraries like Gson exist exactly to avoid such string manipulations.
JsonObject jobj = new Gson().fromJson(YOUR_JSON_HERE, JsonObject.class);
JsonElement value = jobj.get("ParamThatINeed");
value will contain the element associated with the ParamThatINeed key.
I have the following type of JSON I want to send to Java (I'm using Jersey and the default JSON Parser it comes with)
{ "something" : "1", "someOtherThing" : "2" , ... }
But instead of creating an Object with all these properties in Java, I would like to have a Single HashMap (or whatever) that will allow me to still have access to the Key and the Value
Is such a thing possible?
I don't really have any code that does the transformation, I use Jersey like this
#POST
#Path("/purchase")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public StatusResult purchase(UserPurchaseRequest upr) {
}
If i put properties something and someOtherThing as Strings in my UserPurchaseRequest object, everything will come in fine, but I want to have everything in one structure (because I don't know how many values I will get, and I need their names as well)
Yes, it is possible. But still, it depends on what JSON java API you are using. For example using Jackson JSON you can create HashMap json string like this
ObjectMapper obj = new ObjectMapper();
String json = pbj.writeValue(<HashMap object>);
or vice-versa
HashMap obj = obj.readValue(json, HashMap.class);
Note - org.codehaus.jackson.map.ObjectMapper
You just need to add a Property to your Object like this
private HashMap<String,String> purchaseValues;
Jersey takes care of the rest, for some reason while you are debugging, most of the entries appear as null in the HashMap
i meet a problem. the org.Json lib's JSONObject do not have a equals method. but it have a toString method. I want to "abc".equals(JsonObject.toStirng()). here is the problem.
toStirng() string is not sorted. for exmple {"aa":"11","bb":"22"}, maybe, toStirng is this :
{"bb":"22","aa":"11"}, the String not equals, but json object actually equals. I decomplie the
org.json.JSONObject:
private Map map;
public JSONObject()
{
map = new HashMap();
}
i do not have the source code, i want to use asm.lib to modify the class.
so, i want to change one places , one is :
public JSONObject()
{
map = new HashMap(); -->map = new LinkedHashMap();
}
so, the string generated from toString() will be sorted, that is what i wanted.
I do know how to add a field, but i do not know how to Modify and delete a filed or a
method.
Brothers or Sisters is your time, thanks :-)
The json.org Java source is available there: https://github.com/douglascrockford/JSON-java. It is opensource but no license is specified.
You can then modify the source code.