Mapping JSON to Class not working - java

I have a class which contains other some properties of another classes and when I try to convert from json to my class, there is an error displayed.
This is my class:
import org.jongo.marshall.jackson.oid.MongoObjectId;
import org.json.JSONObject;
import java.util.List;
public class BusinessTravelDTO {
#MongoObjectId
private String id;
private String travelerId;
private BusinessTravelStatus status;
List<FlightDTO> flights;
List<HotelDTO> hotels;
List<CarDTO> cars;
public BusinessTravelDTO() { }
public BusinessTravelDTO(JSONObject data) {
this.travelerId = data.getString("travelerId");
this.status = BusinessTravelStatus.valueOf(data.getString("status"));
this.flights = HandlerUtil.getInputFlights(data.getJSONArray("flights"));
this.hotels = HandlerUtil.getInputHotels(data.getJSONArray("hotels"));
this.cars = HandlerUtil.getInputCars(data.getJSONArray("cars"));
}
public JSONObject toJson() {
return new JSONObject()
.put("id", this.id)
.put("travelerId", this.travelerId)
.put("status", this.status)
.put("flights", this.flights)
.put("hotels", this.hotels)
.put("cars", this.cars);
}
And here is where I try to convert to class:
public static JSONObject acceptBusinessTravel(JSONObject input) {
String btId = getStringField(input, "id");
MongoCollection businessTravels = getBTCollection();
// Here is the problem...
BusinessTravelDTO bt = businessTravels.findOne(new ObjectId(btId)).as(BusinessTravelDTO.class);
bt.setStatus(BusinessTravelStatus.Accepted);
businessTravels.save(bt);
return new JSONObject().put("message", "The business travel has been ACCEPTED by your manager. Check your email.");
}
Here is the error I receive:
"error": "org.jongo.marshall.MarshallingException: Unable to unmarshall result to class path.data.BusinessTravelDTO from content { \"_id\" : { \"$oid\" : \"59d6905411d58632fd5bd8a5\"} , \"travelerId\"
In jongo docs is specified that the class should have an empty constructor... http://jongo.org/#mapping I have 2 constructors, I have tried also with #JsonCreator, but no success... :(
Do you have an idea why it doesn't convert? Could it be something related to fields inside BusinesTravelDTO like List CarDTO for ex ?

I finnally found the solution;
There is needed an empty constructor in all classes FlightDTO, HotelDTO, CarDTO plus I should rewrite the toJson method as following:
public JSONObject toJson() {
JSONObject obj = new JSONObject().put("id", this.id).put("travelerId", this.travelerId).put("status", this.status);
if (flights != null) {
JSONArray flightArray = new JSONArray();
for (int i = 0; i < flights.size(); ++i) {
flightArray.put(flights.get(i).toJson());
}
obj.put("flights", flightArray);
}
if (hotels != null) {
JSONArray hotelArray = new JSONArray();
for (int i = 0; i < hotels.size(); ++i) {
hotelArray.put(hotels.get(i).toJson());
}
obj.put("hotels", hotelArray);
}
if (cars != null) {
JSONArray carArray = new JSONArray();
for (int i = 0; i < cars.size(); ++i) {
carArray.put(cars.get(i).toJson());
}
obj.put("cars", carArray);
}
return obj;
}
And this is the FlightDTO;
public class FlightDTO {
#MongoObjectId
private String id;
private String departure;
private String arrival;
private String airline;
private Double price;
public FlightDTO() {
}
public FlightDTO(JSONObject data) {
this.departure = data.getString("departure");
this.arrival = data.getString("arrival");
this.airline = data.getString("airline");
this.price = data.getDouble("price");
}
public JSONObject toJson() {
return new JSONObject()
.put("id", this.id)
.put("departure", this.departure)
.put("arrival", this.arrival)
.put("airline", this.airline)
.put("price", this.price);
}
}
now it works well! :)

Related

Deserialize a JSON payload to object base on JSON integer property

I have below classes:
public class Result<T> {
public int code;
public Object meta;
public T data;
}
public class User {
public int id;
public String name;
}
public class Error {
public String field;
public String message;
}
I want to deserialize a JSON payload based on code field. If code >= 10, return Result<ArrayList<Error>>, otherwise return Result<User>
Currently, I map JSON to Result<Object> first, then check the code field. Based on that value I make second map to desired object.
ObjectMapper mapper = new ObjectMapper();
Result<Object> tempResult = mapper.readValue(json, new TypeReference<Result<Object>>() {});
if (tempResult.code < 10) {
Result<User> result = mapper.readValue(json, new TypeReference<Result<User>>() {});
return result;
} else {
Result<ArrayList<Error>> result = mapper.readValue(json, new TypeReference<Result<ArrayList<Error>>>() {});
return result;
}
Is there an elegant way to do this without deserializing it 2 times?
You need to implement custom TypeIdResolver:
class UserTypeIdResolverBase extends TypeIdResolverBase {
#Override
public String idFromValue(Object value) {
throw new IllegalStateException("Not implemented!");
}
#Override
public String idFromValueAndType(Object value, Class<?> suggestedType) {
throw new IllegalStateException("Not implemented!");
}
#Override
public JsonTypeInfo.Id getMechanism() {
return JsonTypeInfo.Id.CUSTOM;
}
#Override
public JavaType typeFromId(DatabindContext context, String id) {
if (Integer.parseInt(id) < 10) {
return context.getTypeFactory().constructType(new TypeReference<Result<User>>() {});
}
return context.getTypeFactory().constructType(new TypeReference<Result<List<Error>>>() {});
}
}
and declare it for a Result class:
#JsonTypeInfo(property = "code", use = JsonTypeInfo.Id.CUSTOM, visible = true)
#JsonTypeIdResolver(UserTypeIdResolverBase.class)
class Result<T>

How do i create a POST request using jax -rs

I have two classes PlaylistResource which has a method createPlaylist which takes an object of type PlaylistRequest. I want to create a POST request on localhost:9999/playlists I am using Postman and I am not sure how to pass the object of PlaylistRequest which is request to the method createPlaylist.
#XmlType(propOrder= {"title", "artistSeeds", "numberOfSongs"})
#XmlAccessorType(XmlAccessType.FIELD)
public class PlaylistRequest {
private String title = "";
#XmlElement(name = "seeds")
private List<String> artistSeeds;
#XmlElement (name = "size")
private int numberOfSongs = 0;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public List<String> getArtistSeeds() {
return artistSeeds;
}
public void setArtistSeeds(List<String> artistSeeds) {
this.artistSeeds = artistSeeds;
}
public int getNumberOfSongs() {
return numberOfSongs;
}
public void setNumberOfSongs(int numberOfSongs) {
this.numberOfSongs = numberOfSongs;
}
}
The other class:
#Path("playlists")
public class PlaylistResource implements PlaylistApi {
#Override
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response createPlaylist(PlaylistRequest request) {
if(request == null) {
System.out.println("Was here");
throw new ClientRequestException(new ErrorMessage("no parameter passed."));
}
try {
List<Song> playList = new ArrayList<>();
List<Song> songs = new ArrayList<>();
List<String> artistsIds = new ArrayList<>();
ArtistResource artistsResources = new ArtistResource();
int playlistDefaultSize = 10;
int i = 0;
do {
playList.add(songs.get(i));
i++;
}while( i < playlistDefaultSize);
Playlist playlist = new Playlist();
playlist.setTitle(request.getTitle());
playlist.setSize(songs.size());
playlist.setTracks(playList);
return Response.status(Response.Status.CREATED.getStatusCode()).entity(playlist).build();
} catch (Exception e) {
throw new RemoteApiException(new ErrorMessage(e.getMessage()));
}
}
}
Change this parameter from data class to string,
public Response createPlaylist(PlaylistRequest request) {
to
public Response createPlaylist(String request) {
then convert it using GSON into your data class.
PlaylistRequest request = new Gson().fromJson(request, new TypeToken<PlaylistRequest >(){}.getType());
Simply add a JSON object in Body of request, select Raw Json in Postman and paste the following object:
NOTE: Add a key Content-Type and set its value to application/json in Header of Request
{
"title": "Some title",
"artistSeeds": [
"string1",
"string2"
],
"numberOfSongs": 0
}
HEADER
BODY

Map with LIst using Collectors.toMap in Java 8

I like convert below code to java stream,
HashMap<String, List<Data>> heMap = new HashMap<String, List<Data>>();
for (Data heData : obj) {
String id = heData.getData().getId() + heData.getPlanData().getCode()
+ heData.getPlanData().getId();
if (!heMap.containsKey(id)) {
CitizenHElist = new ArrayList<Data>();
CitizenHElist.add(heData);
heMap.put(id, CitizenHElist);
} else {
heMap.get(id).add(heData);
}
}
I tried the below code using stream, but i am not succeed on this.
heMap=obj.stream().collect(Collectors.toMap(t->getKey(t), obj.stream().collect(Collectors.toList())));
private String getKey(Data heData){
String id = heData.getData().getId() + heData.getPlanData().getCode()
+ heData.getPlanData().getId();
return id;
}
This is the job for groupingBy collector:
import static java.util.stream.Collectors.groupingBy;
Map<String, List<Data>> heMap = obj.stream().collect(groupingBy(d -> getKey(d)));
Note that this will use some unspecified implementations of Map and List. Currently, it happens to be HashMap and ArrayList, but that might change in the future.
Grouping on the bases of a field -
import java.util.*;
import java.util.stream.*;
public class Main
{
public static void main (String[]args)
{
System.out.println ("Hello World");
List < Data > dataList = getDataList();
System.out.println (dataList);
Map < String, List < Data >> dataMap =
dataList.stream ().collect (Collectors.groupingBy (d->d.code));
System.out.println (dataMap);
}
static List < Data > getDataList(){
List < Data > dataList = new ArrayList <> ();
dataList.add (new Data (1, "Prince", "102"));
dataList.add (new Data (2, "Rahul", "102"));
dataList.add (new Data (3, "Sunny", "103"));
dataList.add (new Data (4, "Mitul", "104"));
dataList.add (new Data (5, "Amit", "105"));
dataList.add (new Data (6, "Ashish", "105"));
return dataList;
}
}
class Data
{
int id;
String name;
String code;
public Data (int id, String name, String code)
{
this.id = id;
this.name = name;
this.code = code;
}
public String toString ()
{
return String.format ("id:%s,name:%s,code:%s", id, name, code);
}
}
not sure your data structure but you want to do something like below, which is working.
import java.util.*;
import java.util.stream.Collectors;
class Data {
String stud_id;
String stud_name;
String stud_location;
public Data(String string, String string2, String string3) {
this.stud_id=string;
this.stud_location=string2;
this.stud_name=string3;
}
public Object getData() {
return this.stud_id;
}
}
class Temp3
{
public static void main(String args[])
{
Map<String, List<Data>> heMap=new HashMap<String, List<Data>>();
Data data1=new Data("1","11","111");
Data data2=new Data("2","22","222");
List<Data> obj=new ArrayList<Data>();
obj.add(data1);
obj.add(data2);
for (Data heData : obj)
{
String id = "2";
if (!heMap.containsKey(id))
{
ArrayList<Data> CitizenHElist = new ArrayList<Data>();
CitizenHElist.add(heData);
heMap.put(id, CitizenHElist);
}
else
{
heMap.get(id).add(heData);
}
}
heMap=obj.stream().collect(Collectors.groupingBy(w -> w.stud_location));
System.out.println(heMap);
}
}

how to write Hibernate Criteria to take nested objects by Projection List?

I want to take Nested object values in Hibernate Projection List. I having Pojo 'Charge' and 'Tariff' class with OneToMany and ManyToOne relations.
My sample code is as following:
Charge
private String id;
private Tariff tariff;
private String name;
#OneToMany(cascade= {CascadeType.ALL},fetch=FetchType.EAGER,mappedBy="charge")
public Tariff getTariff() {
return tariff;
}
public void setTariff(Tariff tariff) {
this.tariff = tariff;
}
Tariff
private String id;
private String amount;
private Charge charge;
#ManyToOne(cascade={CascadeType.PERSIST},fetch=FetchType.EAGER)
#JoinColumn(name="charge_id")
public Charge getCharge() {
return charge;
}
public void setCharge(Charge charge) {
this.charge = charge;
}
I want to take amount value from tariff by charge model.
I write sql criteria that works ie.
SELECT tariff.amount,charge.name FROM charge,tariff WHERE
charge.name LIKE 's%';
and i tried with following criteria.
Criteria cr = getSession().createCriteria(Charge.class,"charge")
.createAlias("charge.tariff","tariff")
.setProjection(Projections.projectionList()
.add(Projections.property("chargeName"),"chargeName")
.add(Projections.property("id"),"id")
.add(Projections.property("tariff.amount"),"amount"))
.add(Restrictions.like("chargeName", name+"%"))
.setResultTransformer(Transformers.aliasToBean(Charge.class));
return cr.list();
I just check with restclient it returns null Value. How to write for Criteria for this sql Query ?
I've experienced this kind of requirement. I tried to get nested objects as nested objects using Transformers.aliasToBean, which will not work. By default, Transformers.aliasToBean don't have the capability to select nested object as nested object.
You can take a look at my question
Using Projecions to fetch a particular column from child table
To get Nested object as nested object, you need a Custom Transformer which is capable of doing that.
Here's a Custom Transformer written by samiandoni
https://github.com/samiandoni/AliasToBeanNestedResultTransformer
From the provided Readme in that link
class Person {
private Long id;
private String name;
private Car car;
// getters and setters
}
class Car {
private Long id;
private String color;
// getters and setters
}
List<Person> getPeople() {
ProjectionList projections = Projections.projectionList()
.add(Projections.id().as("id"))
.add(Projections.property("name").as("name"))
.add(Projections.property("c.id").as("car.id"))
.add(Projections.property("c.color").as("car.color"));
Criteria criteria = getCurrentSession().createCriteria(Person.class)
.createAlias("car", "c")
.setProjection(projections)
.setResultTransformer(new AliasToBeanNestedResultTransformer(Person.class));
return (List<Person>) criteria.list();
}
// each car of Person will be populated
The above transformer is capable of Fetching first level Nested object as Nested object and it doesn't support further deep nested objects. So after some digging I've found another Custom transformer which is capable of Fetching deep Nested objects as Nested objects
Note:
Author: Miguel Resendiz
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.HibernateException;
import org.hibernate.property.PropertyAccessor;
import org.hibernate.property.PropertyAccessorFactory;
import org.hibernate.property.Setter;
import org.hibernate.transform.AliasToBeanResultTransformer;
import org.hibernate.transform.AliasedTupleSubsetResultTransformer;
import org.hibernate.transform.ResultTransformer;
/**
* Help to transform alises with nested alises
*
* #author Miguel Resendiz
*
*/
public class AliasToBeanNestedResultTransformer extends
AliasedTupleSubsetResultTransformer {
private static final long serialVersionUID = -8047276133980128266L;
private static final int TUPE_INDEX = 0;
private static final int ALISES_INDEX = 1;
private static final int FIELDNAME_INDEX = 2;
private static final PropertyAccessor accessor = PropertyAccessorFactory
.getPropertyAccessor("property");
private final Class<?> resultClass;
private Object[] entityTuples;
private String[] entityAliases;
private Map<String, Class<?>> fieldToClass = new HashMap<String, Class<?>>();
private Map<String, List<?>> subEntities = new HashMap<String, List<?>>();
private List<String> nestedAliases = new ArrayList<String>();
private Map<String, Class<?>> listFields = new HashMap<String, Class<?>>();
public boolean isTransformedValueATupleElement(String[] aliases,
int tupleLength) {
return false;
}
public AliasToBeanNestedResultTransformer(Class<?> resultClass) {
this.resultClass = resultClass;
}
public Object transformTuple(Object[] tuple, String[] aliases) {
handleSubEntities(tuple, aliases);
cleanParams(tuple, aliases);
ResultTransformer rootTransformer = new AliasToBeanResultTransformer(
resultClass);
Object root = rootTransformer.transformTuple(entityTuples,
entityAliases);
loadSubEntities(root);
cleanMaps();
return root;
}
private void handleSubEntities(Object[] tuple, String[] aliases)
throws HibernateException {
String fieldName = "";
String aliasName = "";
try {
for (int i = 0; i < aliases.length; i++) {
String alias = aliases[i];
if (alias.contains(".")) {
String[] sp = alias.split("\\.");
StringBuilder aliasBuilder = new StringBuilder();
for (int j = 0; j < sp.length; j++) {
if (j == 0) {
fieldName = sp[j];
} else {
aliasBuilder.append(sp[j]);
aliasBuilder.append(".");
}
}
aliasName = aliasBuilder.substring(0,
aliasBuilder.length() - 1);
nestedAliases.add(alias);
manageEntities(fieldName, aliasName, tuple[i]);
}
}
} catch (NoSuchFieldException e) {
throw new HibernateException("Could not instantiate resultclass: "
+ resultClass.getName() + " for field name: " + fieldName
+ " and alias name:" + aliasName);
}
}
private Class<?> findClass(String fieldName) throws NoSuchFieldException,
SecurityException {
if (fieldToClass.containsKey(fieldName)) {
return fieldToClass.get(fieldName);
} else {
Class<?> subclass = resultClass.getDeclaredField(fieldName)
.getType();
if (subclass.equals(List.class) || subclass.equals(Set.class)) {
if (subclass.equals(List.class)) {
listFields.put(fieldName, LinkedList.class);
} else {
listFields.put(fieldName, HashSet.class);
}
Field field = resultClass.getDeclaredField(fieldName);
ParameterizedType genericType = (ParameterizedType) field
.getGenericType();
subclass = (Class<?>) genericType.getActualTypeArguments()[0];
}
fieldToClass.put(fieldName, subclass);
return subclass;
}
}
#SuppressWarnings("unchecked")
private void manageEntities(String fieldName, String aliasName,
Object tupleValue) throws NoSuchFieldException, SecurityException {
Class<?> subclass = findClass(fieldName);
if (!subEntities.containsKey(fieldName)) {
List<Object> list = new ArrayList<Object>();
list.add(new ArrayList<Object>());
list.add(new ArrayList<String>());
list.add(FIELDNAME_INDEX, subclass);
subEntities.put(fieldName, list);
}
((List<Object>) subEntities.get(fieldName).get(TUPE_INDEX))
.add(tupleValue);
((List<String>) subEntities.get(fieldName).get(ALISES_INDEX))
.add(aliasName);
}
private void cleanParams(Object[] tuple, String[] aliases) {
entityTuples = new Object[aliases.length - nestedAliases.size()];
entityAliases = new String[aliases.length - nestedAliases.size()];
for (int j = 0, i = 0; j < aliases.length; j++) {
if (!nestedAliases.contains(aliases[j])) {
entityTuples[i] = tuple[j];
entityAliases[i] = aliases[j];
++i;
}
}
}
#SuppressWarnings({ "unchecked", "rawtypes" })
private void loadSubEntities(Object root) throws HibernateException {
try {
for (String fieldName : subEntities.keySet()) {
Class<?> subclass = (Class<?>) subEntities.get(fieldName).get(
FIELDNAME_INDEX);
ResultTransformer subclassTransformer = new AliasToBeanNestedResultTransformer(
subclass);
Object subObject = subclassTransformer.transformTuple(
((List<Object>) subEntities.get(fieldName).get(0))
.toArray(),
((List<Object>) subEntities.get(fieldName).get(1))
.toArray(new String[0]));
Setter setter = accessor.getSetter(resultClass, fieldName);
if (listFields.containsKey(fieldName)) {
Class<?> collectionClass = listFields.get(fieldName);
Collection subObjectList = (Collection) collectionClass
.newInstance();
subObjectList.add(subObject);
setter.set(root, subObjectList, null);
} else {
setter.set(root, subObject, null);
}
}
} catch (Exception e) {
throw new HibernateException(e);
}
}
private void cleanMaps() {
fieldToClass = new HashMap<String, Class<?>>();
subEntities = new HashMap<String, List<?>>();
nestedAliases = new ArrayList<String>();
listFields = new HashMap<String, Class<?>>();
}
}
Just replace samiandoni's Transformer with the above transformer. It's capable of fetching further deep Nested Objects as respective Objects.
My solution is very basic. It's not as clean as a proper result transformer but it's useful when you just need to do a quick projection for a few properties.
Instead of .add(Projections.property("tariff.amount"),"amount"))
type .add(Projections.property("tariff.amount"),"tariffAmount"))
Then, just add a setter on your root object "setTariffAmount".
public void setTariffAmount(String tariffAmount) {
this.tariff = (this.tariff==null) ? new Tariff() : tariff;
tariff.setAmount(tariffAmount);
}
The drawback is that it "dirties" your object with extra methods.
The AliasToBeanNestedResultTransformer does not handle Multilevel Nested DTO's. Meaning, you won't be able to do company.employee.location each in its own DTO.
Here is a Transformer I wrote that handles Multilevel Nested DTOs. You may used it by calling:
criteria.setResultTransformer(
AliasToBeanNestedMultiLevelResultTransformer(mappingBean));
Hope it helps.
public class AliasToBeanNestedMultiLevelResultTransformer extends AliasedTupleSubsetResultTransformer {
private static final long serialVersionUID = -8047276133980128266L;
public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) {
return false;
}
private boolean initialized;
private Class<?> resultClass;
private Map<String,Class<?>> clazzMap = new HashMap<>();
private Map<String,Setter> settersMap = new HashMap<>();
public AliasToBeanNestedMultiLevelResultTransformer(Class<?> resultClass) {
this.resultClass = resultClass;
}
public Object transformTuple(Object[] tuples, String[] aliases) {
Map<String,Object> nestedObjectsMap = new HashMap<>();
Object result;
try {
result = resultClass.newInstance();
if (!initialized){
initialized = true;
initialize(aliases);
}
for (int a=0;a<aliases.length;a++){
String alias = aliases[a];
Object tuple = tuples[a];
Object baseObject = result;
int index = alias.lastIndexOf(".");
if(index>0){
String basePath = alias.substring(0, index);
baseObject = nestedObjectsMap.get(basePath);
if (baseObject == null){
baseObject = clazzMap.get(basePath).newInstance();
nestedObjectsMap.put(basePath, baseObject);
}
}
settersMap.get(alias).set(baseObject, tuple,null);
}
for (Entry<String,Object> entry:nestedObjectsMap.entrySet()){
Setter setter = settersMap.get(entry.getKey());
if (entry.getKey().contains(".")){
int index = entry.getKey().lastIndexOf(".");
String basePath = entry.getKey().substring(0, index);
Object obj = nestedObjectsMap.get(basePath);
setter.set(obj, entry.getValue(), null);
}
else{
setter.set(result, entry.getValue(), null);
}
}
}catch ( InstantiationException | IllegalAccessException e) {
throw new HibernateException( "Could not instantiate resultclass: " + resultClass.getName() );
}
return result;
}
private void initialize(String[] aliases) {
PropertyAccessor propertyAccessor = new ChainedPropertyAccessor(
new PropertyAccessor[] {
PropertyAccessorFactory.getPropertyAccessor( resultClass, null ),
PropertyAccessorFactory.getPropertyAccessor( "field" )
}
);
for (int a=0;a<aliases.length;a++){
String alias = aliases[a];
Class<?> baseClass = resultClass;
if (alias.contains(".")){
String[] split = alias.split("\\.");
StringBuffer res = new StringBuffer();
for (int i=0;i<split.length;i++){
if (res.length()>0) res.append(".");
String item = split[i];
res.append(item);
String resString = res.toString();
if (i==split.length-1){
clazzMap.put(resString,baseClass);
settersMap.put(resString, propertyAccessor.getSetter(baseClass, item));
break;
}
Class<?> clazz = clazzMap.get(resString);
if (clazz==null){
clazz = propertyAccessor.getGetter(baseClass,item).getReturnType();
settersMap.put(resString, propertyAccessor.getSetter(baseClass, item));
clazzMap.put(resString,clazz);
}
baseClass = clazz;
}
}
else{
clazzMap.put(alias, resultClass);
settersMap.put(alias, propertyAccessor.getSetter(resultClass, alias));
}
}
}
}

How to right declare a composite java JSON object from string?

i have this string which i'm using for testing of api:
{"limit":30, "offset":"0", "filters": [{"property":"vlc.vlc","operator":"=","value":"DEKU113829"}]}
I would like to create JSOn object for processing in Android app using the:
JSONObject json = new JSONObject();
json.put("limit", 30);
json.put("offset", "0");
But i don't know how to create "filters" section using put method...
What is the right and most effective solution for this?
JSONObject/JSONArray supports a "builder-esque" pattern and put can be chained - it will return the same (but modified) object.
JSONObject json =
new JSONObject()
.put("limit", 30)
.put("offset", "0") /* but should be 0? */
.put("filters",
new JSONArray()
.put(new JSONObject()
.put("property", "vlc.vlc")
.put("operator", "=")
.put("value", "DEKU113829")
)
);
Alternatively, look into a POJO mapper like Gson, which I would recommend overall for ease of use and consistency.
Try this...
JSONObject json = new JSONObject();
json.put("limit", 30);
json.put("offset", "0");
JSONArray js_array = new JSONArray();
JSONObject json_obj = new JSONObject();
json_obj.put("property", "vlc.vlc");
json_obj.put("operator", "=");
json_obj.put("value", "DEKU113829");
js_array.put(json_obj);
json.put("filters",js_array);
Use the Gson Library. Your model objects for the JSON will be
public class MainModel
{
private int limit ;
public int getlimit()
{
return this.limit;
}
public void setlimit(int limit)
{
this.limit = limit;
}
private String offset ;
public String getoffset()
{
return this.offset;
}
public void setoffset(String offset)
{
this.offset = offset;
}
private ArrayList<Filter> filters ;
public ArrayList<Filter> getfilters()
{
return this.filters;
}
public void setfilters(ArrayList<Filter> filters)
{
this.filters = filters;
}
}
public class Filter
{
private String property ;
public String getproperty()
{
return this.property;
}
public void setproperty(String property)
{
this.property = property;
}
private String operator ;
public String getoperator()
{
return this.operator;
}
public void setoperator(String operator)
{
this.operator = operator;
}
private String value ;
public String getvalue()
{
return this.value;
}
public void setvalue(String value)
{
this.value = value;
}
}
You can populate your filter object and create MainModel object and add the filter object to it. Next use Gson library as below to get your json string
Gson gsonParser = new Gson();
String jsonString = gsonParser.toJson(mainModelObject);

Categories