Jackson- How to process the request data passed as JSON (Netsed Json)? - java

{
"DistributionOrderId" : "Dist_id_1",
"oLPN":
{
"Allocation":
{
"AID": "12345"
},
"Allocation":
{
"AID": "123456" ,
"SerialNbr": "SRL001",
"BatchNbr": "LOT001"
"RevisionNbr": "RVNBR1"
}
},
"oLPN":
{
"Allocation":
{
"AID": "12123"
}
"Allocation":
{
"AID": "12124"
}
}
}
I have a JSON request passed from the vendor, How to store the values as Java POJO and use them further?
Edit : Added attributes to JSON

As you aren't using the usual camel case conventions common in jackson databinding I would suggest defining a java object with the appropriate annotations. The object is not currently valid json. If for example the json looks like this:
{
"DistributionOrderId" : "Dist_id_1",
"oLPN": [ ... ]
}
Where each oLPN in the array is an object like this:
{
"Allocation": [{ "AID": ... }, { "AID": ... }, ... ]
}
You can write a class for distribution orders
public class DistributionOrder {
#JsonProperty("DistributionOrderId") private String id;
#JsonProperty("oLPN") private List<OLPN> olpn;
// getters and setters
}
Then another for the OLPN object
public class OLPN {
#JsonProperty("Allocation") private String allocation;
#JsonProperty("AID") private String aid;
// getters and setters
}
Then you can use an object mapper as appropriate. For example
ObjectMapper mapper = ... // get your object mapper from somewhere
DistributionOrder distributionOrder = mapper.readValue(raw, DistributionOrder.class);
See also object mapper javadoc

json key can't repeat, and the repeat key with value will be discard.
i have format your json text, may be it is like following expression:
{
"DistributionOrderId" : "Dist_id_1",
"oLPN":
[
{
"Allocation":
[
{
"AID": "123456" ,
"SerialNbr": "SRL001",
"BatchNbr": "LOT001",
"RevisionNbr": "RVNBR1"
},
{
"AID": "12345"
}
]
},
{
"Allocation":
[
{
"AID": "12123"
},
{
"AID": "12124"
}
]
}
]
}
and this struct match the java object is
class DistributionOrder{
#JsonProperty("DistributionOrderId")
String distributionOrderId;
List<OLPN> oLPN;
}
class OLPN {
#JsonProperty("Allocation")
List<Allocation> allocation;
}
class Allocation{
String AID;
#JsonProperty("SerialNbr")
String serialNbr;
#JsonProperty("BatchNbr")
String batchNbr;
#JsonProperty("RevisionNbr")
String revisionNbr;
}

Related

GSON parser skipping Object while looping over json

I have a Json array that I parse to GSON. It has the following content:
[
{
"type": "way",
"id": 70215497,
"nodes": [
838418570,
838418571
]
},
{
"type": "way",
"id": 70215500,
"nodes": [
838418548,
838418626
]
}
]
I tried to parse it using the following sample of code:
while (jsonReader.hasNext()){
Element type = gson.fromJson(jsonReader, Element.class);
if (type.GetType().contentEquals("way")) {
Way way = gson.fromJson(jsonReader, Way.class);
System.out.println(way.GetId());
}
}
Where Element is simply
public class Element {
private String type;
public String GetType() {
return type;
}
}
and Way is
public class Way {
private long id;
private String type;
List<Long> nodes;
public long GetId() {
return id;
}
}
Now for some reason only 70215500 will print out. And this happens for a few other elements in the real code. Why is that ?
Edit: It basically only reads 1/2 object. Why?
You do not need to read Element class first and after that Way class. Read Way and check it's type:
try (JsonReader jsonReader = new JsonReader(new FileReader(jsonFile))) {
jsonReader.beginArray();
while (jsonReader.hasNext()) {
Way way = gson.fromJson(jsonReader, Way.class);
if (way.getType().contentEquals("way")) {
System.out.println(way.getId());
}
}
}
Above code should print all ids.

can Rest API parse hashmap<string,object>?

i would like to know if rest api while consuming input parameter can do the following:
let's say my json object have the following parameters:
string name;
string adress;
hashmap<string,object> content;
and here's an exemple of what can be sent:
{
"name": "AZ",
"adress": "US",
"content": {
"clients": [
{
"client_ref":"213",
"commands" : {
"subCommands": [
{
"num":"1",
"price":"10euro"
},
{
"num":"12,
"price":"10euro"
}
]
}
},
{
"client_ref":"213",
"commands" : {
"subCommands": [
{
"num":"1",
"price":"10euro"
},
{
"num":"12,
"price":"10euro"
}
]
}
}
]
}
}
the question is can rest build the hashmap where the object can itself have n child of hashmap type ... ?
(i'm using jersey as rest implementation )
Assuming that you have a JSON provider such as Jackson registered and your model class looks like:
public class Foo {
private String name;
private String address;
private Map<String, Object> content;
// Getters and setters
}
The following resource method:
#Path("foo")
public class Test {
#POST
#Consumes(MediaType.APPLICATION_JSON)
public Response post(Foo foo) {
...
}
}
Can handle a request like:
POST /api/foo HTTP/1.1
Host: example.org
Content-Type: application/json
{
"name": "AZ",
"adress": "US",
"content": {
"clients": [
{
"client_ref": "213",
"commands": {
"subCommands": [...]
}
},
{
"client_ref": "213",
"commands": {
"subCommands": [...]
}
}
]
}
}
content is an Object, not a map.
"content": {
"clients": [
{
"client_ref":"213",
"commands" : {
"subCommands": [
{
"num":"1",
"price":"10euro"
},
{
"num":"12,
"price":"10euro"
}
]
}
},
{
"client_ref":"213",
"commands" : {
"subCommands": [
{
"num":"1",
"price":"10euro"
},
{
"num":"12,
"price":"10euro"
}
]
}
}
]
}
And this is Java Object presentation.
public class Content {
private List<Client> clients;
//Getters and setters
}
public class Client {
private String clientRef;
private List<Command> commands;
//Getters and setters
}
//And so on, define other classes.
To answer your question, yes, you can build a map.
Check this example, please. It tells how to parse an unknown json (in case you don't know the exact structure of your json object).
https://stackoverflow.com/a/44331104/4587961
Then you can build a map with fields
Map<String, Object> where some values of this map will be nested maps.
you can use javax.ws.rs.core.GenericEntity to wrap collections with generic types (your HashMap).
#GET
#Path("/mapping")
#Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Response getAllMapContents() {
Map<String,Object> map = new HashMap<String,Object>();
map.put("Hello", "World");
map.put("employee", new Employee(1,"nomad"));
GenericEntity<Map<String,Object>> entity = new GenericEntity<Map<String,Object>>(map) {};
return Response.ok(entity).build();
}
I checked it and found it working Please find the response below. Thank you.
{
"Hello": "World",
"employee": {
"id": 1,
"name": "nomad"
}
}

Spring RestTemplate parse JSON object with variable keyname

I have a REST API call that returns the following JSON object. I need to parse this with Spring's RestTemplate. The problem is that the first key ISBN:0132856204 is variable (the numbers change depending on the book). How would I go about doing this?
{
"ISBN:0132856204": {
"publishers": [
{
"name": "Pearson"
}
],
"pagination": "xxiv, 862p",
"identifiers": {
"isbn_13": [
"978-0-13-285620-1"
],
"openlibrary": [
"OL25617855M"
]
},
"weight": "1340 grams",
"title": "Computer networking",
"url": "https://openlibrary.org/books/OL25617855M/Computer_networking",
"number_of_pages": 862,
"cover": {
"small": "https://covers.openlibrary.org/b/id/7290810-S.jpg",
"large": "https://covers.openlibrary.org/b/id/7290810-L.jpg",
"medium": "https://covers.openlibrary.org/b/id/7290810-M.jpg"
},
"publish_date": "2013",
"key": "/books/OL25617855M",
"authors": [
{
"url": "https://openlibrary.org/authors/OL31244A/James_F._Kurose",
"name": "James F. Kurose"
},
{
"url": "https://openlibrary.org/authors/OL658909A/Keith_W._Ross",
"name": "Keith W. Ross"
}
],
"subtitle": "A Top-Down Approach"
}
}
In here "ISBN:0132856204" is a value and also a key for your business.
To get ISBN first, what about wrapping json content with 1 more closure?
{
"yourAwesomePlaceHolderKey" :
{
"ISBN:0132856204": {
......
}
}
}
First get the ISBN key as a value, then your ISBN value can be used as a key to get related content.
First goal will be extracting -String1,Object1- pair where String1 is "yourAwesomePlaceholderKey" and second goal will be again extracting -String2,Object2- from Object1 where String2 is your ISBN key.
This is the way I solved it, using JsonPath for getting the book out of the JSON object and Jackson for mapping it to a Book object:
RestTemplate restTemplate = new RestTemplate();
String isbn = "0132856204";
String endpoint = "https://openlibrary.org/api/books?jscmd=data&format=json&bibkeys=ISBN:{isbn}";
//Get JSON as String
String jsonString = restTemplate.getForObject(endpoint, String.class, isbn);
//Configure JsonPath to use Jackson for mapping
Configuration.setDefaults(new Configuration.Defaults() {
private final JsonProvider jsonProvider = new JacksonJsonProvider();
private final MappingProvider mappingProvider = new JacksonMappingProvider();
#Override
public JsonProvider jsonProvider() {
return jsonProvider;
}
#Override
public MappingProvider mappingProvider() {
return mappingProvider;
}
#Override
public Set<Option> options() {
return EnumSet.noneOf(Option.class);
}
});
//Parse the JSON as a book
Book book = JsonPath.parse(jsonString).read("$.ISBN:" + isbn, Book.class);
You can use JsonProperty to solve
#JsonProperty("ISBN:0132856204")

How to fix Gson JSON parsing from LinkedTreeMap to ArrayList?

I'm using Retrofit+Gson for parsing JSON.
When I try parse response from Google Places API (ok, I don't try parse, I just try to make model for this response) and I get some error.
This is response from Google Place API:
{
"predictions" : [
{
"description" : "Николаевская область, Украина",
"id" : "3bd747cc4efc2288da48942b909ce18a053c2060",
"matched_substrings" : [
{
"length" : 5,
"offset" : 0
}
],
"place_id" : "ChIJydRVsbqaxUARLq1R8Q3RgpM",
"reference" : "ClRPAAAAwseWiG8NUMt7TqSqz9rMP8R2M4rX7-cMRmIp4OCYL-VdRSr5B5T_PMwWzYOydVStVpYDvm0ldXYPEzxFAuvn1LqhtWHdROhsERwvmx0tVlwSEFdMw0sOe3rDaB2AqKKmF-YaFLvhiEOz3Bklv5-iTa7QQORILVCU",
"structured_formatting" : {
"main_text" : "Николаевская область",
"main_text_matched_substrings" : [
{
"length" : 5,
"offset" : 0
}
],
"secondary_text" : "Украина"
},
"terms" : [
{
"offset" : 0,
"value" : "Николаевская область"
},
{
"offset" : 22,
"value" : "Украина"
}
],
"types" : [ "administrative_area_level_1", "political", "geocode" ]
}, ...],
"status" : "OK"
}
This is my model for this response:
public class GetGoogleMapPlacesResponse {
#SerializedName("predictions")
private List<GooglePlace> googlePlaces;
public List<GooglePlace> getGooglePlaces() {
return googlePlaces;
}
public void setGooglePlaces(List<GooglePlace> googlePlaces) {
this.googlePlaces = googlePlaces;
}
}
But when Retrofit try's to parse response to model I get error:
java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.myapp.net.rest.response.GetGoogleMapPlacesResponse
And this is raw response in Debug mode:
You're missing a constructor of GetGoogleMapPlacesResponse model.
public class GetGoogleMapPlacesResponse {
private List<GooglePlace> googlePlaces;
private String status;
public GetGoogleMapPlacesResponse(List<GooglePlace> googlePlaces, String status) {
this.googlePlaces = googlePlaces;
this.status = status;
}
...getters & setters
}
But i highly suggest you to use AutoValue with Gson extension and then your model will look like this :
#AutoValue
public abstract class GetGoogleMapPlacesResponse {
#SerializedName("predictions") public abstract List<GooglePlace> googlePlaces;
public abstract String status;
}
For more info look here : https://github.com/rharter/auto-value-gson

Create complex json objects using gson

How to create javabean for gson for the below JSON script?
{
"header": [
{
"title": {
"attempts": 3,
"required": true
}
},
{
"on": {
"next": "abcd",
"event": "continue"
}
},
{
"on": {
"next": "",
"event": "break"
}
}
]
}
I'm trying to build the javabean for this JSON output. I'm not able to repeat the fieldname on.
Please suggest any solutions.
You will need multiple classes to accomplish this. I made some assumptions with the naming, but these should suffice:
public class Response {
private List<Entry> header;
private class Entry {
private Title title;
private On on;
}
private class Title {
int attempts;
boolean required;
}
private class On {
String next, event;
}
}
You can test it with a main() method like:
public static void main(String[] args) {
// The JSON from your post
String json = "{\"header\":[{\"title\":{\"attempts\":3,\"required\":true}},{\"on\":{\"next\":\"abcd\",\"event\":\"continue\"}},{\"on\":{\"next\":\"\",\"event\":\"break\"}}]}";
Gson gson = new GsonBuilder().setPrettyPrinting().create();
Response response = gson.fromJson(json, Response.class);
System.out.println(response.header.get(0).title.attempts); // 3
System.out.println(response.header.get(1).on.next); // abcd
System.out.println(gson.toJson(response)); // Produces the exact same JSON as the original
}

Categories