creating a POJO containing only some elements from the response - java

I'm trying to read from a JSON response using a pojo. The response has many attributes but I only need few, I created the POJO with only those attributes, but when I'm trying to read it. it fails to parse it.
JSON response:
[
{
"attr_1":1,
"attr_2":2,
"attr_3":3,
"attr_4":4,
"attr_5":5,
},
{
"attr_1":10,
"attr_2":20,
"attr_3":30,
"attr_4":40,
"attr_5":50,
}
]
my POJO:
#JsonIgnoreProperties(ignoreUnknown = true)
public class MyPOJO {
#JsonProperty("attr_2")
private int attr_2;
#JsonProperty("attr_4")
private int attr_4;
public int getattr_2() { return attr_2; }
public void setattr_2(int attr_2) { this.attr_2 = attr_2;}
public int getattr_4() { return attr_4; }
public void setattr_4(int attr_4) { this.attr_4 = attr_4;}
}
I only need attr_2 and attr_4, and not the others.
this is how I'm trying to read the response:
MyPOJO[] arr = response.readEntity(MyPOJO[].class);
but it fails at this step. do we really need to have all the attributes in my POJO as there are many and I need few attributes, don't want to have redundant code?

I was able to solve the issue. I created an empty constructor and it worked. previously I had a constructor with the two needed attributes only.

Related

Serializing JSON object containing nested objects with dynamic property names with Jackson

I have been struggling with this, and I can't seem to get it right. I have a Java Spring Boot project and I need to create an API that returns the following JSON in what I called AggregatedResponse:
{
"shipments": {
"987654321": ["BOX", "BOX", "PALLET"]
},
"track": {
"123456789": "COLLECTING"
},
"pricing": {
"NL": 14.242090605778
"CN": 20.503467806384
}
}
Each of the objects (shipments, track, pricing) need to be fetched from an external API.
This means that I need to create the AggregatedResponse and use a setter whenever I'm receiving the different data from the external APIs.
The number in the shipments (987654321) comes from the request param passed to the external API that retrieves shipments. The track number (123456789) also comes from an external API.
This is the Java structure I have so far:
public class AggregatedResponse {
private TrackResponse tracking;
private ShipmentsResponse shipments;
private PricingResponse pricing;
public ShipmentsResponse getShipments() {
return shipments;
}
public void setShipmentsResponse(ShipmentsResponse value) {
this.shipments = value;
}
public TrackResponse getTrackResponse() {
return tracking;
}
public void setTrackResponse(TrackResponse trackResponse) {
this.tracking = trackResponse;
}
public PricingResponse getPricing() {
return pricing;
}
public void setPricing(PricingResponse value) {
this.pricing = value;
}
}
The problem I have is that like I mentioned, the shipments and track JSON object have dynamic names, so I have tried different strategies for creating the TrackResponse and the ShipmentsResponse.
How could I do this?
Create a Map from the data instead of class so you can define the keys and serialize it.

Issue while mapping my json to model fields attribute value set 0

while mapping json with my object, my attribute set default value to zero, here is my field attribute
in my ModelDTO
private int ExcessRqstType;
public int getExcessRqstType() {
return ExcessRqstType;
}
public void setExcessRqstType(int excessRqstType) {
ExcessRqstType = excessRqstType;
}
Here is my json
{
"ExcessRqstType": 2,
"balance": 100000,
"ExcessFor": 1020
}
In output it gives me '0'
System.out.println(objModel.getExcessRqstType());
"ExcessRqstType" value in my json is '2' but when it mapped i get '0'.
I am stuck in this issue.
Issue resolve, this issue because of case sensitivity, I change "ExcessRqstType" to "excessRqstType" in my DTO as well as in model, also changed in json request object
private int excessRqstType;
public int getExcessRqstType() {
return excessRqstType;
}
public void setExcessRqstType(int excessRqstType) {
excessRqstType = excessRqstType;
}

Passing values from database in "allowableValues"?

I am using Swagger version 2 with Java Spring. I have declared a property and it works fine and it generates a drop down list of value I assigned.
#ApiParam(value = "Pass any one Shuttle provider ID from the list", allowableValues = "1,2,3,4,10")
private Long hotelId;
Now, I need a way to populate this list which is passed in allowableValues from my database as it could be random list as well as huge data. How can I assign list of values dynamically from database in this allowableValues?
This question is bit old, I too faced the same problem so thought of adding here which may help some one.
//For ApiModelProperty
#ApiModelProperty(required = true, allowableValues = "dynamicEnum(AddressType)")
#JsonProperty("type")
private String type;
Created a component which implements ModelPropertyBuilderPlugin
#Component
#Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1)
public class ApiModelPropertyPropertyBuilderCustom implements ModelPropertyBuilderPlugin {
private final DescriptionResolver descriptions;
#Autowired
public ApiModelPropertyPropertyBuilderCustom(DescriptionResolver descriptions) {
this.descriptions = descriptions;
}
public void apply(ModelPropertyContext context) {
try {
AllowableListValues allowableListValues = (AllowableListValues) FieldUtils.readField(context.getBuilder(),
"allowableValues", true);
if(allowableListValues!=null) {
String allowableValuesString = allowableListValues.getValues().get(0);
if (allowableValuesString.contains("dynamicEnum")) {
String yourOwnStringOrDatabaseTable = allowableValuesString.substring(allowableValuesString.indexOf("(")+1, allowableValuesString.indexOf(")"));
//Logic to Generate dynamic values and create a list out of it and then create AllowableListValues object
context.getBuilder().allowableValues(allowableValues);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public boolean supports(DocumentationType delimiter) {
return SwaggerPluginSupport.pluginDoesApply(delimiter);
}
}
Similary for ApiParam we can create component which will implement ParameterBuilderPlugin
#Override
public void apply(ParameterContext context) {
#SuppressWarnings("Guava") final Optional<ApiParam> apiParam =
context.resolvedMethodParameter().findAnnotation(ApiParam.class);
if (apiParam.isPresent()) {
final String allowableValuesString = apiParam.get().allowableValues();
//Your logic here
context.parameterBuilder().allowableValues(allowableValues);
}
}
You need to create constructor in SwaggerConfiguration class.
#Autowire service and withdraw data you need from database
assign this to final variable
assign this final variable to allowableValues in annotation
enjoy not efficient api
private final String allowableValues;
public SwaggerConfiguration() {
List<YourEntitiy> list = someService.findAll();
//code to get every value you need and add create comma separated String
StringJoiner stringJoiner = new StringJoiner(",");
stringJoiner.add(list.get(0).getValue());
this.allowableValues = stringJoiner.toString();
}
#ApiParam(allowableValues = allowableValues)
But I think it's bad idea getting all ids from database just to create allowable values. Just validate in api method if that id exist and/or Create new api to get ids from database, use pagination from Spring Data project, like PageImpl<> javadocs

Parsing json with gson and java

I am struggling to parse a json output with Java and gson, but I am really stuck.
I would appreciate any suugestion.
This is my sample JSON file:
{
"sportId": 29,
"last": 26142386,
"league": [
{
"id": 1833,
"events": [
{
"id": 383911973,
"starts": "2015-01-22T21:00:00Z",
"home": "America de Natal",
"away": "Barras",
"rotNum": "901",
"liveStatus": 0,
"status": "O",
"parlayRestriction": 0
},
{
"id": 383911974,
"starts": "2015-01-22T21:00:00Z",
"home": "Baraunas RN",
"away": "ASSU RN",
"rotNum": "904",
"liveStatus": 0,
"status": "O",
"parlayRestriction": 0
}
]
}
]
}
My target is to a make a 2-dimensional array (or something similar) of the form:
leagueId, eventId, home, away
------------------------------
1 1 a b
. . . .
. . . .
etc etc etc etc
in order to insert the data in a MYSQL table.
I have write the following classes:
public class Fixtures {
int last;
int sportId;
ArrayList<Leagues> league = new ArrayList<Leagues>();
public ArrayList<Leagues> getListOfLeagues() {
return league;
}
public int getSportId(){
return sportId;
}
public int getLast(){
return last;
}
}
public class Leagues {
int id;
ArrayList<Events> events;
public int getLeagueId(){
return id;
}
public ArrayList<Events> getListOfEvents() {
return events;
}
}
public class Events {
int id;
String home;
String away;
public int getEventId(){
return id;
}
public String getHome() {
return home;
}
public String getAway() {
return away;
}
}
and
Gson gson = new GsonBuilder().create();
Fixtures fixture = gson.fromJson(jsonsource, Fixtures.class);
System.out.println(fixture.getSportId());
System.out.println(fixture.getLast());
ArrayList<Leagues> Leagues = fixture.getListOfLeagues();
Dont know how to proceed :(
The real answer here is to not do it this way.
Have you looked at Hibernate? It's like Entity for C#. It allows you to interact with your relational database as an object oriented entity structure, which is how we're used to thinking about things.
Typically, when you have a set of data as input and need to put that data in a database, you need to make a few considerations:
Does my input properly represent how my data is stored?
Does my relational model (database) represent how my data is used?
If one or both of these is a "no", can I change either of them to make them true?
If your model is good and your input is good (which your input looks fine), then you should have no need to put your data into an intermediate layer, you should be able to loop over the applicable fields and put the data in your database. If you can't do that, I'd recommend restructuring your database. Again, I know this is kind of a sideways answer, but you did ask for suggestions :)
Try jackson to parse JSON to java object, you get some help from here where a similar JSON was parsed to couple of java objects.
JSON parsing example using jackson
Try it and let me know if you find any issue.
Ok, I figured out how to do the iteration:
for (Leagues leg : Leagues) {
System.out.println(leg.getLeagueId());
ArrayList<Events> Events = leg.getListOfEvents();
for (Events event : Events) {
System.out.println(event.getEventId());
System.out.println(event.getHome());
System.out.println(event.getAway());
System.out.println(event.getStarts());
}
}
Thanks all.

Transition from old Java to Play, Servlet issue

I have to move from an old Java code to a new one using Play! Framework.
In the old code, I called a Java servlet using Ext-Js (Javascript Framework) using this way :
function getTree()
{
var store = Ext.create('Ext.data.TreeStore',
{
root:
{
text: 'System',
id: 'root',
expanded: true
},
proxy:
{
type: 'ajax',
url: 'TreeServlet',
extraParams:
{
mode:'getChildren'
},
reader:
{
type:'json',
root:'result'
}
}
});
Now, I would like to use Play! to do the same, but I do not know how to use it.
. In routes.conf:
GET /tree controllers.Application.makeTree()
. In controller.Application:
public static Result makeTree(){
// What shoul I put here to call the "Servlet"
}
I do not want to use Servlet, but I don't know how to do it.
Thank you for you help!
EDIT 1:
Thank you to all of you!
Here is how I eventually manage to achieve my goal:
public class Tree extends Controller
{
private MenuManager menuManager;
String node;
String mode;
String hash;
ObjectNode response;
public void createTree() throws IOException{
this.menuManager = MenuManager.getMenuManager();
getParams();
createJson(mode, node, hash);
}
public static Result returnJson() throws IOException{
Tree t = new Tree();
t.createTree();
return ok(t.response);
}
}
And in routes:
GET /tree controllers.Tree.returnJson()
What do you guys think? Good practice?
In earlier play frameworks you have to create only static methods for each and every request handler in controller.
But in the newer version (after play 2.0) you don't need to have static methods you can use normal public methods and configure it in routes prefixed with '#' symbol.
And don't maintain or declare attributes within controller class.
Because play is an event driven framework not like oridinary servlet based framework.
It provides REST and it doesn't maintain any httpsession like in servlets.
Session is available in the form of cookies only.
Below is the remodified version of your code,
public class TreeController extends Controller
{
public void createTree() throws IOException{
MenuManager menuManager = MenuManager.getMenuManager();
String mode = request().getQueryString("mode");
String node = request().getQueryString("node");
String hash = request().getQueryString("hash");
TreeNodeDto treeObject = menuManager.buildTree();
ok(treeObject.toJson());
}
}
public class BaseDto<T extends BaseDto<T>> implements Serializable{
public JsonNode toJson() {
return Json.toJson(this);
}
public T fromJson(JsonNode jsonObject) {
return (T) Json.fromJson(jsonObject, this.getClass());
}
}
public static class TreeNodeDto extends BaseDto {
public String hash;
public String name;
public Set<TreeNodeDto> children;
// Override equals and hashcode, because we are using "set" to maintain the child nodes.
}
routes
GET /tree #controllers.TreeController.createTree()
Hope this will give some ideas.
Cheers..!!!
Check the WS object: https://www.playframework.com/documentation/2.3.x/JavaWS
It seems that the return from the Servlet is a Json so check how to process json in play here: https://www.playframework.com/documentation/2.3.x/JavaJsonActions
I believe something like that should do it
public static Promise<Result> makeTree() {
final Promise<Result> resultPromise = WS.url("TreeServlet").setHeader("Content-Type", "application/json").get().map(
new Function<WSResponse, Result>() {
public Result apply(WSResponse response) {
return ok("Feed title:" + response.asJson().findPath("result"));
}
}
);
return resultPromise;
}
Below is the structure for your http request in play,
public static Result makeTree() {
TreeDto treeDto=new TreeDto();
JsonNode jsonResponse = Json.newObject();
try {
treeDto = <<Logic to get the tree objects from db>>;
if(treeDto != null) {
jsonResponse = Json.toJson(treeDto);
}
} catch (XODAOException e) {
Logger.error("Error while building the tree.", e);
jsonResponse = generateErrorResponse("Error while building tree.", e);
}
return ok(jsonResponse);
}

Categories

Resources