I have two JSON files, called "pickevent1" and "pickevent2". I have to compare if both files are matching; if they don't match, I need to know where they don't match.
pickevent1
{
"pickEventActivities": [{
"orderId": "215",
"lineNbr": 0,
"pick": "EACH",
"activations": [{
"activationType": "Si",
"activationValue": "31"
}]
}]
}
pickevent2
{
"pickEventActivities": [{
"orderId": "115",
"lineNbr": 1,
"pick": "Hello",
"activations": [{
"activationType": "Bi",
"activationValue": "3"
}]
}]
}
I created a pick event POJO class:
#JsonRootName(value = "pickEventActivities")
#Data
#JsonPropertyOrder({ "orderId", "lineNbr", "pick"})
class PickEvent {
String orderId;
String lineNbr;
String pick;
List<Activation> activations;
}
and a Activation POJO class:
#Data
#JsonPropertyOrder({ "activationType", "activationValue"})
public class Activation {
String activationType;
String activationValue;
}
To make sure it works, I created a test class:
public void compareJson() throws Exception {
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
PickEvent result1 = objectMapper.readValue(new File("src/../pickevent1.json"), PickEvent.class);
PickEvent result2 = objectMapper.readValue(new File("src/../pickevent2.json"), PickEvent.class);
assertEquals(result1, result2);
}
But when I am doing assertSame(result1,result2) its giving me null for json values:
Exception in thread "main" java.lang.AssertionError: expected same:<PickEvent(orderId=null, lineNbr=null, pick=null, activations=null)> was not:<PickEvent(orderId=null, lineNbr=null, pick=null, activations=null)>
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.failNotSame(Assert.java:828)
at org.junit.Assert.assertSame(Assert.java:771)
at org.junit.Assert.assertSame(Assert.java:782)
at JsonDiff.PickEventDiff.comparejson(PickEventDiff.java:26)
at JsonDiff.PickEventDiff.main(PickEventDiff.java:32)
It should give me an assertion error, but the test succeeds.
It should give me an assertion error, but the test succeeds.
Because you use objectMapper.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);. In fact, an exception occurred during the parsing process.
Try:
public void compareJson() throws Exception {
final ObjectMapper objectMapper = new ObjectMapper();
Wrapper wrapper = objectMapper.readValue(new File(""), Wrapper.class);
Wrapper wrapper2 = objectMapper.readValue(new File(""), Wrapper.class);
System.out.println(wrapper.equals(wrapper2));
}
#Data
static class Wrapper {
List<PickEvent> pickEventActivities;
}
You are trying to read a PickEvent Object but you're actually sending a list there.
Please change your json to
{
"pickEventActivities": {
"orderId": "115",
"lineNbr": 1,
"pick": "Hello",
"activations": [{
"activationType": "Bi",
"activationValue": "3"
}]
}
}
or try changing your code to
List<PickEvent> list1 = objectMapper.readValue(new File("src/../pickevent1.json"), new ParameterizedTypeReference<PickEvent>(){});
Here is my github repo for Intellij Idea plugin.
Basically JSON comparator implemented in java. It compares JSON by fields, values and objects in array
Related
I'm trying to parse a json file that looks like this
{
"foo": "v2",
"bar": [
"abc/bcf<object#twenty>.xyz",
"abc/fgh<object#thirtu>.xyz"
]
}
The code I have is currently this:
Config.java
private static final ObjectMapper OBJECT_MAPPER;
static {
OBJECT_MAPPER = new ObjectMapper();
OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
OBJECT_MAPPER.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true);
OBJECT_MAPPER.enableDefaultTyping();
}
#JsonCreator
public Config(
#JsonProperty(value = "foo", required = true) final String version,
#JsonProperty(value = "bar") final List<String> barTypes) {
// rest of constructor
}
public static Config fromJson(final Reader reader)
throws IOException {
return OBJECT_MAPPER.readValue(reader, Config.class);
}
I am getting an error:
Failed to parse type 'abc/bcf<object#twenty>.xyz' (remaining: '<object#twenty>.xyz'): Cannot locate class 'abc/bcf', problem: abc/bcf"
Is there something special I need to do in order to read "<" as String?
I'm reading the file into a BufferReader with StandardCharsets.UTF_8 like this:
try (BufferedReader reader = Files.newBufferedReader(configFile.toPath(), StandardCharsets.UTF_8)) {
config = Config.fromJson(reader);
}
Edit: I actually do need defaultTyping for an ArrayList that has polymorphic types:
"Vehicles": [
"java.util.ArrayList",
[
{
"name": "Car"
},
{
"name": "Train"
}
]
I currently use a MixIn for declaring the subtypes. However, this stops working if I remove DefaultTyping.
Remove OBJECT_MAPPER.enableDefaultTyping(); and it will work fine. This method is anyway deprecated.
In case you want to read automatic polymorphic types, use activateDefaultTyping(PolymorphicTypeValidator ptv).
Following is Response body:
{
"Updated_Fields": [
"a",
"b",
"c",
"d"
],
"Invalid_Fields": [
"cd",
"ab"
]
}
I want to check that whether response body has
two fields in invalid_field block
'cd' and 'ab' should be there in invalid_field block
JSONArray JSONResponseBody = new JSONArray(response.body().asString());
Assert.assertEquals(JSONResponseBody.getJSONObject(0).getString("Invalid_Fields"), "cd");
response.jsonPath().param("Invalid_Fields", "cd");
assertThat( response.asString(), hasJsonPath("Invalid_Fields.ab"));
Getting an error
One way you can use a library like gson to convert String to Java object and then apply standard Java logic ( sample below )
Gson Maven Dependency
private static final List INVALID_DATA = Arrays.asList("cd", "ab");
public static void main(String[] args)
{
String input = "{ \"Updated_Fields\": [ \"a\", \"b\", \"c\", \"d\" ], \"Invalid_Fields\": [ \"cd\", \"ab\" ] }";
Gson gson = new Gson();
FieldData data = gson.fromJson(input, FieldData.class);
System.out.println(isInvalidFields(data.Invalid_Fields));
}
private static boolean isInvalidFields(List<String> Invalid_Fields) {
if(CollectionUtils.isEmpty(Invalid_Fields) || Invalid_Fields.size() != 2) {
return false;
}
return Invalid_Fields.containsAll(INVALID_DATA);
}
Definiton of class mapping to this data:
public class FieldData
{
public List<String> Updated_Fields;
public List<String> Invalid_Fields;
}
I want to deserialize a json like this
{
"0":{"name":"Alice"},
"1":{"name":"Bob"}
}
to a java collection( set or list, not map).
I want to change the default behavior of CollectionDeserializer to support this and config it as a global configuration. Any way to to this?
If you really have this structure (an object as a container and not an array, which could be handled much easier):
import com.fasterxml.jackson.databind.*;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
public class Main {
public static void main(String[] args) throws IOException {
String json = "{\"0\":{\"name\":\"Alice\"}, \"1\":{\"name\":\"Bob\"}}";
ObjectMapper mapper = new ObjectMapper();
JsonNode obj = mapper.readValue(json, JsonNode.class);
Iterator<Map.Entry<String, JsonNode>> userEntries = obj.fields();
while(userEntries.hasNext()){
Map.Entry<String, JsonNode> userEntry = userEntries.next();
System.out.println(userEntry.getKey() + " => " + userEntry.getValue());
}
}
}
You can achieve this task using gson api.
The code is as follows:
String yourJson = "{\"0\":{\"name\":\"Alice\"}, \"1\":{\"name\":\"Bob\"}}";
Gson gson = new Gson();
Type tarType = new TypeToken<Map<String,Map<String,String>>>(){
}.getType();
gson.fromJson(yourJson, tarType);
For this you need to add following:
com.google.gson.Gson
Why not to turn your JSON document into an array as:
{"persons":[{"name":"Alice"},{"name":"Bob"}]}
Then define a corresponding JSON schema (assuming PersonArray is the file name):
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Some description",
"type" : "object",
"properties" : {
"persons" : {
"type" : "array",
"items" : { "$ref": "#/definitions/person" }
}
},
"definitions": {
"person" : {
"type": "object",
"description": "A person",
"properties": {
"name": { "type": "string" }
}
}
}
}
and take advantage of Jackson Data Binding API by using jsonschema2pojo-maven-plugin Maven plugin to generate POJOs in Java (alternatively, you can manually implement POJOs).
Once POJOs are generated, you can use ObjectMapper to deserialise JSON document in the following way:
ObjectMapper mapper = new ObjectMapper();
PersonArray personArray = mapper.readValue(serialisedJsonDocument, PersonArray.class);
The elements of your JSON document will be stored inside PersonArray object as:
List<Person> persons = new ArrayList<Person>();
You could also add additional properties to the Person object if you needed.
I've got one Pojo object which is serialized by Jersey using jackson:
public class BookOfFriendsAnswer {
private Map<String, List<BookSummary>> books;
public BookOfFriendsAnswer() {
}
public BookOfFriendsAnswer(Map<String, List<BookSummary>> books) {
this.books = books;
}
public Map<String, List<BookSummary>> getBooks() {
return books;
}
public void setBooks(Map<String, List<BookSummary>> books) {
this.books = books;
}
}
The serialization produces a JSon like this one:
{
"books": {
"entry": [
{
"key": "54567bbce4b0e0ef9379993e",
"value": "BookSummary{id='54567bbde4b0e0ef9379993f', title='title 1', authors=[Steve,James] } BookSummary{id='54567bd9e4b0e0ef93799940', title='Title 2', authors=[Simon, Austin]}"
}
]
}
}
However, when I'm trying to deserialize the message from my client like this:
mapper.readValue(json, clazz)
I get the following error:
Unrecognized field "key" (class com.example.server.api.BookSummary), not marked as ignorable
I don't know if the problem comes from the JSOn produced by the server or the deserialization on client's side.
Do you know what is the problem and how to correct it?
Thanks a lot
So after a little testing with:
Jersey 1.18.1 (with jersey-json-1.18.1 for JSON support)
Jersey 2.13 (with jersey-media-json-jackson-2.13 for JSON support)
Jersey 2.13 (with jersey-media-moxy-2.13 for JSON support)
The last test (jersey-media-moxy-2.13) was the only one to produce this exact output
{
"books": {
"entry": [
{
"key": "54567bbce4b0e0ef9379993e",
"value": "BookSummary{id='54567bbde4b0e0ef9379993f', title='title 1', authors=[Steve,James] } BookSummary{id='54567bd9e4b0e0ef93799940', title='Title 2', authors=[Simon, Austin]}"
}
]
}
}
That being said, I'll make the assumption you're using a Jersey 2.x version. I'm not sure if there is any configuration in MOXy to better support this use case, but to make things easy, just add the following dependency, and get rid of the MOXy
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey-version}</version>
</dependency>
With this, you will get the correct JSON output
{ // BookOfFriendsAnswer object
"books": { // Map<String, List<BookSummary>> books
"randomKey": [ // String (key) , List<BookSummary> (value)
{ // BookSummary object
"id": "54567bbde4b0e0ef9379993f",
"title": "Title 1",
"authors": ["Steve", "James"]
}
]
}
}
Simple Test
Resource method
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response getResponse() {
BookOfFriendsAnswer books = new BookOfFriendsAnswer();
String id = "randomKey"; <===== Not sure if you want the key to be
the BookSummary id
BookSummary summary = new BookSummary();
summary.setId(id);
summary.setTitle("Title 1");
summary.getAuthors().add("Steve");
summary.getAuthors().add("James");
List<BookSummary> summaries = new ArrayList<>();
summaries.add(summary);
books.getBooks().put("randomKey", summaries);
return Response.ok(books).build();
}
Test With ObjectMapper
#Test
public void testGetIt() throws Exception {
String responseMsg = target.path("book").request().get(String.class);
ObjectMapper mapper = new ObjectMapper();
BookOfFriendsAnswer books = mapper.readValue(
responseMsg, BookOfFriendsAnswer.class);
System.out.println(books);
}
Test Without ObjectMapper - Using the automatically configured Jackson provider
#Test
public void testGetIt() throws Exception {
BookOfFriendsAnswer responseMsg
= target.path("book").request().get(BookOfFriendsAnswer.class);
System.out.println(responseMsg);
}
I think that you should create specific Map type and provide it into deserialization process:
TypeFactory typeFactory = mapper.getTypeFactory();
MapType mapType = typeFactory.constructMapType(HashMap.class, String.class, ArrayList.class);
HashMap<String, List<BookSummary>> map = mapper.readValue(json, mapType);
I'm getting this error when I receive only one single item in a list. I'm using Jersey in the server side REST Web service, I only get the error when the List returned one single element and when it has 0 elements I get java.lang.NullPointerException But when it has more than one it works perfectly, and this is how I'm doing it :
#GET
#Path("getproject")
#Produces(MediaType.APPLICATION_JSON)
public List<Project> getPagedProjects(
#QueryParam("offset") int offset,
#QueryParam("limit") int limit,
#QueryParam("searchKey") String searchKey) throws Exception {
System.out.println("Returning Paged Project ");
return projectService.getPagedProjects(offset, limit, searchKey);
}
Why doesn't Jersey send a list that contains one single item? It is a bug in jersey?
Is there a way to make it always serialize as an array?
This is my JSON data when the web service returns 0 element:
null
And This is my JSON data when web service returns 1 element :
{
"project": {
"abbreviation": "abc",
"customer": "customer1",
"description": "description3",
"icon": "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",
"name": "projectname3",
"plannedEndDate": "2012-05-23T00:00:00+01:00",
"plannedStartDate": "2012-05-23T00:00:00+01:00",
"projectStatus": {
"name": "In Progress"
},
"realEndDate": "2012-05-23T00:00:00+01:00",
"realStartDate": "2012-05-23T00:00:00+01:00"
}
}
And This is my JSON data when web service returns more than 1 element :
{
"project": [
{
"abbreviation": "abd",
"customer": "customer1",
"description": "description1",
"icon": "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",
"name": "projectname1",
"plannedEndDate": "2012-05-25T00:00:00+01:00",
"plannedStartDate": "2012-05-23T00:00:00+01:00",
"projectStatus": {
"name": "Opened"
},
"realEndDate": "2012-05-25T00:00:00+01:00",
"realStartDate": "2012-05-23T00:00:00+01:00"
},
{
"abbreviation": "bd",
"customer": "customer1",
"description": "description2",
"icon": "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",
"name": "projectname2",
"plannedEndDate": "2012-05-23T00:00:00+01:00",
"plannedStartDate": "2012-05-23T00:00:00+01:00",
"projectStatus": {
"name": "Closed"
},
"realEndDate": "2012-05-23T00:00:00+01:00",
"realStartDate": "2012-05-23T00:00:00+01:00"
},
{
"abbreviation": "abc",
"customer": "customer1",
"description": "description3",
"icon": "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",
"name": "projectname3",
"plannedEndDate": "2012-05-23T00:00:00+01:00",
"plannedStartDate": "2012-05-23T00:00:00+01:00",
"projectStatus": {
"name": "In Progress"
},
"realEndDate": "2012-05-23T00:00:00+01:00",
"realStartDate": "2012-05-23T00:00:00+01:00"
}
]
}
And in android side I deserialize the JSON response like this :
Gson gson = new Gson();
final ProjectContainer container = gson.fromJson(resultat, ProjectContainer.class);
final ListView lv = (ListView) findViewById(R.id.list);
adaptateur = new ProjectAdapter(ProjectActivity.this, R.layout.ligne_project, container);
lv.setAdapter(adaptateur);
This is my ProjectContainer class :
public class ProjectContainer {
#SerializedName("project")
List<Project> projects ;
public List<Project> getProjects() {
return projects;
}
public void setProjects(List<Project> projects) {
this.projects = projects;
}
}
I would greatly appreciate your help to solve this problem. Thanks in advance
Your issue results really weird for me... it seems that there must be some problem with Jersey's JSON serialization of single element arrays... if you Google "Jersey JSON single element arrays" you'll find the same issue, like here or here. I don't know too much about Jersey, so I can't help you with that...
That said, I can suggest a workaround using manually parsing in Gson, to adapt your parsing to the 2 different responses (object or array). You could do something like this:
//manually parsing until get the "project" element...
JsonParser parser = new JsonParser();
JsonObject rootObejct = parser.parse(yourJsonString).getAsJsonObject();
JsonElement projectElement = rootObejct.get("project");
Gson gson = new Gson();
List<Project> projectList = new ArrayList<>();
//Check if "project" element is an array or an object and parse accordingly...
if (projectElement.isJsonObject()) {
//The returned list has only 1 element
Project project = gson.fromJson(projectElement, Project.class);
projectList.add(project);
}
else if (projectElement.isJsonArray()) {
//The returned list has >1 elements
Type projectListType = new TypeToken<List<Project>>() {}.getType();
projectList = gson.fromJson(projectElement, projectListType);
}
//Now you have a List<Project> projectList with one or many Project elements,
//depending on the response...
Note that you don't need your class ProjectContainer.
Something like this should work for you, although obviously the best thing would be fix the serialization issue!
Basically, your web service is broken in terms of how it's replying. If there's only one object for project it's returning only an object instead of an array.
MikO's answer solves the problem but another approach is encapsulating that logic in a custom deserializer:
class MyDeserializer implements JsonDeserializer<ProjectContainer> {
#Override
public ProjectContainer deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) throws JsonParseException {
JsonObject jo = je.getAsJsonObject().getAsJsonObject("project");
if (jo.isJsonArray()) {
return new Gson().fromJson(je, ProjectContainer.class);
} else {
Project p = jdc.deserialize(jo, Project.class);
List<Project> pList = new ArrayList<Project>(1);
pList.add(p);
ProjectContainer pc = new ProjectContainer();
pc.setProjects(pList);
return pc;
}
}
}
Then you can use:
Gson gson = new GsonBuilder()
.registerTypeAdapter(ProjectContainer.class, new MyDeserializer())
.build();
ProjectContainer pContainer = gson.fromJson(myJson, ProjectContainer.class);
I ended up using Jackson library instead of gson to parse the json response. It automatically converts object into ArrayList. It is pretty much similar to gson in terms of ease of use. Hope it helps!