maping of JSON response using jackson [duplicate] - java

This question already has answers here:
Make Jackson interpret single JSON object as array with one element
(3 answers)
Closed 2 years ago.
I have a rest endpoint with the following response
{
"Shops": {
"Shop": [
{
"RowID": "1",
"Penalties": {
"Penalty": [
{
"PenaltyCode": "abc-01",
"PenaltyCount": "1"
},
{
"PenaltyCode": "abc-02",
"PenaltyCount": "2"
}
]
},
"VisitOutComes": {
"VisitOutCome": {
"TaskOutComeName": "text",
"TaskOutComeCount": "1"
}
}
}
]
}
}
I need to insert the response in a RDMS using hibernate.
I already done the hibernate part and the rest client part.
I am confused how to map the json to java classes.
I write the follwing classes , getter and setter are omitted for clarity.
public class Shops {
#JsonProperty("Shop")
private ArrayList<Shop> shop ;
public class Shop {
#JsonProperty("VisitOutComes")
private VisitOutComes visitOutComes ;
#JsonProperty("Penalties")
private Penalties penalties ;
#JsonProperty("RowID")
private String rowID ;
public class VisitOutComes {
#JsonProperty("VisitOutCome")
ArrayList<VisitOutCome> visitOutCome ;
public class Penalties {
#JsonProperty("Penalty")
ArrayList<Penalty> penalty ;
public class VisitOutCome {
#JsonProperty("TaskOutComeCount")
private String TaskOutComeCount;
#JsonProperty("TaskOutComeName")
private String TaskOutComeName ;
public class Penalty {
#JsonProperty("penaltyCode")
private String penaltyCode ;
#JsonProperty("penaltyCount")
private String penaltyCount ;
Then I wirte the main method as follows :
ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
String path = "C:\\jars\\response.json" ;
Shops shops = mapper.readValue(new File(path),Shops.class);
Finally I get the error
Cannot deserialize instance of java.util.ArrayList jscksondemo.VisitOutCome out of START_OBJECT token
I appreciate any help on how to create the maping for this json file.

Try with this JSON:
{
"Shops": {
"Shop": [
{
"RowID": "1",
"Penalties": {
"Penalty": [
{
"PenaltyCode": "abc-01",
"PenaltyCount": "1"
},
{
"PenaltyCode": "abc-02",
"PenaltyCount": "2"
}
]
},
"VisitOutComes": {
"VisitOutCome": [
{
"TaskOutComeName": "text",
"TaskOutComeCount": "1"
}
]
}
}
]
}
}
I think the bracket of your VisitOutCome List is not right.

Related

How to consume Json from rest template and map for each element to another Json in Spring Boot

I am not able to map a consumed json to another json to each element by using REST template in Spring Boot
Controller code:
public List<Getrequests> getallrequests() {
List<Getrequests> list=Serviceobj.allrequestdata();
return list;
}
Service code:
public List<Getrequests> allrequestdata() {
String urlGETList = "http://localhost:8082/myapp/userinfo/getusertype/asd454";//get by id call
ResponseEntity<Usertype[]> responseEntity =resttemplateobj.getForEntity(urlGETList, Usertype[].class);
Usertype[]objects = responseEntity.getBody();
List results = admininfoDaoobj.getallrequestsdata();
//results.add(objects);if i un comment this line of code i am getting 1 output means it just add to the list only
return results;
}
Dao code:
public List<Getrequests> getallrequestsdata(){
String hql = "FROM Createrequest";
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
Query<Createrequest> query = getSession().createQuery(hql,Createrequest.class);
List resultlist= query.getResultList();
return resultlist;
}
Getrequests pojo class:
public class Getrequests{
private String userid;
private String username;
private String userphoneno;
.......getters and setters.....
}
User type pojo class:
public class Usertype{
private String usertype;
private String useraddress;
.......getters and setters.....
}
1 output:
[
{
"userid":"asd454",
"username":"satya",
"userphoneno":"1234567890"
},
{
"userid":"asd455",
"username":"satya",
"userphoneno":"1234567890"
}
[
{
"usertype":"admin,agent",
"useraddress:"dsadasd,asdasdsa"
},
{
"usertype":"agent",
"useraddress:"asdasdsa"
},
]
]
2 output
If I comment resultlist.add(objects) in Service code means it's not added to the getrequest list then I am getting below output:
[
{
"userid":"asd454",
"username":"satya",
"userphoneno":"1234567890"
},
{
"userid":"asd455",
"username":"satya",
"userphoneno":"1234567890"
}
]
But I need to map for each userid, I need to display the usertype and user address like below output.
3 Output
[
{
"userid":"asd454",
[
{
"usertype":"admin,agent",
"useraddress:"dsadasd,asdasdsa"
} ]
"username":"satya",
"userphoneno":"1234567890"
},
{
"userid":"asd455",
[
{
"usertype":"agent",
"useraddress:"asdasdsa"
}
]
"username":"satya",
"userphoneno":"1234567890"
}
]
I also tried the rest template call in Dao then also not getting.
How can I map for each userid to display the usertype and user address like as above shown 3 output.
From your snippets, it looks like you want to generate a specific POJO signature.
There are plenty of tools which can give you a stub out of a sample json request.
From your example, i would guess that changing the Getrequests would do the trick,
like :
public class Getrequests{
private String userid;
private String username;
private String userphoneno;
private Usertype userType;
.......getters and setters.....
}
You might need to change it to a list reference as well, depending on your schema and your overall requirement.
EDIT
public class Getrequests{
private String userid;
private String username;
private String userphoneno;
private List<Usertype> userType;
}
If i make the reference a list, then the below samples are the output :
Single object:
{
"userid":"69",
"username":"asd",
"userphoneno":"09876",
"userType":[
{
"usertype":"01",
"useraddress":"1234"
}
]
}
As An array :
[
{
"userid":"94",
"username":"asd",
"userphoneno":"09876",
"userType":[
{
"usertype":"01",
"useraddress":"1234"
}
]
},
{
"userid":"53",
"username":"asd",
"userphoneno":"09876",
"userType":[
{
"usertype":"01",
"useraddress":"1234"
}
]
}
]

Deserialize json file with dynamic fields into class with java

We have a JSON file providing us with data that needs to be loaded in memory, however I'm having a lot of trouble parsing the file as it does not use mapping of fields like I have seen classically:
{
"1er":{
"baccalaureat": [
{
"prog": "genie logiciel",
"limite": 30
},
{
"prog": "genie civil",
"limite": 15
},
{
"prog": "genie electrique",
"limite": 25
},
{
"prog": "Medecine",
"limite": 34
},
{
"prog": "actuariat",
"limite": 25
}
]
},
"2e":{
"maitrise": [
{
"prog": "informatique",
"limite": 25
}
]
},
"3e":{
"doctorat": [
{
"prog": "informatique",
"limite": 21
}
]
}
}
I use to deal with JSON files with "property" : "value" and I was hoping to be able to use jackson annotations. I've tried a test class shaped like this:
public class ClassOne {
#JsonProperty
public String Level;
#JsonProperty
public String[] programs;
}
But alas it does not working, throwing a mismatchedInputException. Of course, but I don't know how to map the properties, then:
private ObjectMapper objectMapper;
private ProgramLimitService programLimitService;
public ProgramLimitsLoader() {
objectMapper = new ObjectMapper();
}
private static List<String> values = new ArrayList<>();
public void load(String path) {
File file = new File(path);
ClassOne[] classes;
try {
classes = objectMapper.readValue(file, ClassOne[].class);
} catch (IOException e) {
throw new FileCantBeOpenException(e.getMessage());
}
}
I feel like it's because the structure of my class while I'm deserializing is wrong, but I can't put the finger on the problem.

Not able to take response body data for assertions while performing operations using rest-assured with java

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;
}

Parsing JSON from API with GSON [duplicate]

This question already has answers here:
Why does Gson fromJson throw a JsonSyntaxException: Expected BEGIN_OBJECT but was BEGIN_ARRAY?
(2 answers)
Closed 3 years ago.
I'm make an API call with retrofit, the problem is the JSON I get from the call. Normally it was a simple Json with an array in it.
[
{
"herbID": 1,
"nameTrival": "Baldrian",
"nameWissenschaft": "Valeriana officinalis",
....
},
{
"herbID": 2,
"nameTrival": "Ringelblume",
"nameWissenschaft": "Calendula officinalis",
....
},
....
]
The new call looks like this
[
[
{
"nameTrival": "Baldrian",
"nameWissenschaft": "Valeriana officinalis",
"hoeheFrom": 20,
"hoeheTo": 200,
"familie": "Baldriangewaechse",
"pflanzentype": "Staude",
"auffaelligkeiten": "Je nach Standort sind die Fiederblätter schmäler oder breiter sowie dunkel- oder hellgrün, oft auch unterschiedlich geformt."
}
],
[
{
"standort": "Ufer"
},
{
"standort": "Graben"
},
{
"standort": "Wiesen"
},
{
"standort": "Waldrand"
}
],
[
{
"gebiet": "Nordeuropa"
},
{
"gebiet": "Südeuropa"
},
{
"gebiet": "Westeuropa"
},
{
"gebiet": "Osteuropa"
},
{
"gebiet": "Südosteuropa"
},
{
"gebiet": "Mitteleuropa"
},
{
"gebiet": "Südwesteuropa"
},
{
"gebiet": "Nordosteuoropa"
},
{
"gebiet": "Nordwesteuropa"
}
],
{
"fieldCount": 0,
"affectedRows": 0,
"insertId": 0,
"serverStatus": 34,
"warningCount": 0,
"message": "",
"protocol41": true,
"changedRows": 0
}
]
I parsed the first Json with the following code
Call<List<Herb>> call = service.getAllHerbs();
call.enqueue(new Callback<List<Herb>>() {
#Override
public void onResponse(Call<List<Herb>> call, Response<List<Herb>> response) {
herbList = response.body();
loadDataList(herbList);
}
#Override
public void onFailure(Call<List<Herb>> call, Throwable t) {
Toast.makeText(PlantListActivity.this, "Unable to load herbs\nCheck your internet connection", Toast.LENGTH_LONG).show();
}
});
The new class looks like this
public class Herb{
ArrayList<Botanical> botanical;
ArrayList<Location> locations;
ArrayList<Area> areas;
public ArrayList<Botanical> getBotanical() {
return botanical;
}
public ArrayList<Location> getLocations() {
return locations;
}
public ArrayList<Area> getAreas() {
return areas;
}
}
With the new Json and the class it always fail with the error "java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $"
Didn't I tell gson that the following is an array, after I declare them as an ArrayList? What is wrong with my class?
EDIT:
The difference between the possible duplicate and my question is, that the other one has arrays with names. My json arrays doesn't have one, that's why I have a hard time parsing them.
If you want to handle response with type Herb class, then you need to modify service response like
Rather than
[{},{},{}] // this is much difficult to handle
Try this which has to be done at server end
{
"botanical":[],
"area" : [],
"location" : []
}
Then call will be Call<Herb> someMethod();
If change not possible
then handle it as JsonArray
Call<JsonArray> someMethod();
By this you can handle existing response and fetching value key and parse as per requirement. But this is not recommended because it's difficult to maintain if future change and require lot of change
The problem is you're telling Gson you have an object of your type. You don't. You have an array of objects of your type. You can't just try and cast the result like that and expect it to magically work ;)
The User guide for Gson Explains how to deal with this
Your new response is very bad. It's impossible to parse that kind of JSON.
It represents array of different objects (different type). So, GSON can do nothing, you have to create a class that is equivalent to the entire response.
Your first JSON response is fine.

Nested JSON Request with Volley -> Escaped chars

I want to make a post request with volley to a REST API.
Therefore, I create a JSONObject and put a JSON String generated from a class in it.
JSONObject jsonObject = new JSONObject();
String json = gson.toJson(MyClazz);
try {
jsonObject.put(PARAM, json);
}
catch (JSONException e1) {
e1.printStackTrace();
}
The problem is that the correct calculated JSON String gets escaped and can't be recognized on the back end.
So toJson() gives something like:
{
"device_identifier":"324234234",
"name":"NameMe",
"list":[
{"prop":"A","prop2":-10},
{"prop":"B","prop2":-12}
]
}
The jsonObject's output is like
{
"PARAM":{
\"device_identifier\":\"324234234\",
\"name\":\"NameMe\",
\"list\":[
{\"prop\":\"A\",\"prop2\":-10},
{\"prop\":\"B\","\prop2\":-12}
]
}
}
I need the PARAM for the JSON structure so I can't give it directly to the REST-API. Any ideas how I can avoid the additional escaping?
You could wrap your MyClazz object with a simple wrapper object, and then pass that wrapped object to Gson's toJson method.
Given this class based on your example JSON,
public class MyClazz {
public String device_identifier;
public String name;
public List<Prop> list;
public class Prop {
public String prop;
public Integer prop2;
}
}
here's a possible wrapper implementation. Note the use of com.google.gson.annotations.SerializedName which tells Gson to use the PARAM key in the JSON representation.
public class MyClazzWrapper {
public MyClazzWrapper(MyClazz myClazz) {
this.myClazz = myClazz;
}
#SerializedName("PARAM")
private MyClazz myClazz;
}
And here's an example using it:
Gson gson = new GsonBuilder().setPrettyPrinting().create();
MyClazz myClazz = gson.fromJson("{\"device_identifier\":\"324234234\",\"name\":\"NameMe\",\"list\":[{\"prop\":\"A\",\"prop2\":-10},{\"prop\":\"B\",\"prop2\":-12}]}", MyClazz.class);
MyClazzWrapper wrapped = new MyClazzWrapper(myClazz);
System.out.println(gson.toJson(wrapped));
The above will print:
{
"PARAM": {
"device_identifier": "324234234",
"name": "NameMe",
"list": [
{
"prop": "A",
"prop2": -10
},
{
"prop": "B",
"prop2": -12
}
]
}
}

Categories