The format of my JSON is :
{"abc": [{
"field_1": "string_1",
"value": 0.304
},
{
"field_1": "string_2",
"value": 0.193
}]}
"abc" is variable, "field_1" and "value" are field names. I want a class in Java which stores this JSON in some format for example:
String t; // should store "abc"
List<myClass> myClassObject; // myClass should contain "field_1" and "value"
myClass.java
String field_1; // should store "string_1" and "string_2"
Double value; // should store 0.304 and 0.193
I want the class myClass.java because in future I may want to add more metadata in JSON response. This is complex object mapping, but I am not able to figure out what should my class be looking like in order to store the JSON response.
For root object do not create new POJO just use Map. Example could look like below:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
import java.io.File;
import java.io.FileReader;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
public class GsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
Gson gson = new GsonBuilder().create();
Type mapType = new TypeToken<Map<String, List<Item>>>() {
}.getType();
Map<String, List<Item>> map = gson.fromJson(new FileReader(jsonFile), mapType);
Map.Entry<String, List<Item>> first = map.entrySet().stream().findFirst().get();
Items items = new Items(first.getKey(), first.getValue());
System.out.println(items);
}
}
class Items {
private final String key;
private final List<Item> items;
public Items(String key, List<Item> items) {
this.key = key;
this.items = items;
}
public String getKey() {
return key;
}
public List<Item> getItems() {
return items;
}
#Override
public String toString() {
return "Items{" +
"key='" + key + '\'' +
", items=" + items +
'}';
}
}
class Item {
#SerializedName("field_1")
private String field;
private Double value;
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public Double getValue() {
return value;
}
public void setValue(Double value) {
this.value = value;
}
#Override
public String toString() {
return "Item{" +
"field='" + field + '\'' +
", value=" + value +
'}';
}
}
Above code prints:
Items{key='abc', items=[Item{field='string_1', value=0.304}, Item{field='string_2', value=0.193}]}
I'm sharing you the sample code:
Main method:
import com.google.gson.Gson;
public class GsonConversion {
public static void main(String[] args) {
String json = "{\"abc\": [{" +
" \"field_1\": \"string_1\"," +
" \"value\": 0.304" +
"}," +
"{" +
" \"field_1\": \"string_2\"," +
" \"value\": 0.193" +
"}]}";
Gson gson = new Gson();
Type mapType = new TypeToken<Map<String, List<Data>>>() {
}.getType();
Map<String, List<Data>> map = gson.fromJson(json, mapType);
Model model= new Model();
map.entrySet().stream().forEach(entry->{
model.setT(entry.getKey());
model.setAbc(entry.getValue());
});
System.out.println("Key:"+model.getT());
model.getAbc().stream().forEach(x->{
System.out.println("Field:"+x.getField_1()+" Value:"+x.getValue());
});
}
}
Parent Model Objects:
i) Model Class
import java.util.ArrayList;
public class Model {
private String t;
private ArrayList<Data> abc = new ArrayList<>();
public String getT() {
return t;
}
public void setT(String t) {
this.t = t;
}
public ArrayList<Data> getAbc() {
return abc;
}
public void setAbc(ArrayList<Data> abc) {
this.abc = abc;
}
}
ii) Data Class
public class Data {
private String field_1;
private Double value;
public Data() {
}
public String getField_1() {
return field_1;
}
public void setField_1(String field_1) {
this.field_1 = field_1;
}
public Double getValue() {
return value;
}
public void setValue(Double value) {
this.value = value;
}
}
Related
The result coming from an external API as..
BIBREF are dynamic, the we do not know how will be fetched
The index is appended to the name "BIBREF+number"
"bib_entries": {
"BIBREF0": {
"ref_id": <str>,
"title": <str>,
},
"BIBREF1": {
"ref_id": <str>,
"title": <str>,
},
...
...
"BIBREF25": {}
},
Defined a pojo as..
public class BibEntries {
private BibRef bibRef;
# ...getters/setters
public class BibRef {
private String ref_id;
private String title;
# ...getters/setters
}
}
Defined the class as:
JsonObject bibEntriesObject = jsonObject.get("bib_entries").getAsJsonObject();
BibEntries bibEntries = new Gson().fromJson(bibEntriesObject, BibEntries.class);
Learning GSON and using GenericTypes seemed confusing. How can i update the above code to read the dynamic objects (using gson 2.8.6)?
With some help from my colleague, here's the solution
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
import java.util.List;
public class Test {
private static final Gson gson = new
GsonBuilder().serializeNulls().setPrettyPrinting().create();
public static void main(String[] args) {
// Original Json Input
String jsonRequest = "{ \"bib_entries\": { \"BIBREF0\": { \"ref_id\": \"One\", \"title\": \"two\"},"
+ "\"BIBREF1\": { \"ref_id\": \"three\", \"title\": \"four\"} } }";
//Convert string to JsonObject
JsonObject convertedObject = new Gson().fromJson(jsonRequest, JsonObject.class);
JsonObject object = convertedObject.get("bib_entries").getAsJsonObject();
//Init Class
BibEntries bibEntries = new BibEntries();
List<BibEntries.Bibref> list = new ArrayList<>();
//Mapping the object to class
object.keySet().stream().forEach((key) -> {
// We can add more here..
BibEntries.Bibref bibref = gson.fromJson(object.get(key), BibEntries.Bibref.class);
list.add(bibref);
bibEntries.setListBibref(list);
});
//Original
System.out.println(convertedObject);
// Print the final result
System.out.println(gson.toJson(bibEntries));
}
public static class BibEntries {
List<Bibref> listBibref;
public static class Bibref {
#SerializedName("ref_id")
private String refId;
#SerializedName("title")
private String title;
public String getRefId() {
return refId;
}
public void setRefId(final String refId) {
this.refId = refId;
}
public String getTitle() {
return title;
}
public void setTitle(final String title) {
this.title = title;
}
}
public List<Bibref> getListBibref() {
return listBibref;
}
public void setListBibref(final List<Bibref> listBibref) {
this.listBibref = listBibref;
}
}
}
To get data from json I used RestTemplate and it works for getting all my data and displaying it on the localhost. The arrayList I got, I want to filter now to get only some data and put it in a new arrayList, but when I try to run it, it gives me "java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to model.Artists"
Should I get the Json data in other way, or the filtering function needs some casting?
The model class
package model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
#JsonIgnoreProperties(ignoreUnknown = true)
public class Artists {
private String ArtistName;
private String Stage;
private String Day;
private String Hour;
public Artists(){
}
public String getArtistName() {
return ArtistName;
}
public void setArtistName(String artistName) {
ArtistName = artistName;
}
public String getStage() {
return Stage;
}
public void setStage(String stage) {
Stage = stage;
}
public String getDay() {
return Day;
}
public void setDay(String day) {
Day = day;
}
public String getHour() {
return Hour;
}
public void setHour(String hour) {
Hour = hour;
}
#Override
public String toString() {
return "Artists [ArtistName=" + ArtistName + ", Stage=" + Stage + ", Day=" + Day + ", Hour=" + Hour + "]";
}
}
The service class
#Service
public class ArtistsWrapper {
private List<Artists> artists;
private final String url ="some_random_website";
/**
* #return the artists
*/
public List<Artists> getArtists() {
RestTemplate restTemplate=new RestTemplate();
this.artists=restTemplate.getForObject(url, List.class);
return artists;
}
public List<Artists> getArtistsByStage(String stage)
{
System.out.println(artists.toString());
List<Artists> result = new ArrayList<Artists>();
for(Artists a: artists)
{
if(stage.equals(a.getStage()))
System.out.println(a.toString()+"\n");
result.add(a);
}
return result;
}
The controller class
#RestController
#RequestMapping("/api")
public class ArtistsController {
#Autowired
ArtistsWrapper aw;
/*#RequestMapping("/artists")
public List<Artists> artists() {
return aw.getArtists();
}
*/
#RequestMapping("/artists")
public List<Artists> artistsByStage(#RequestParam(value="stage", defaultValue="Main") String name) {
return aw.getArtistsByStage(name);
}
}
I have a problem with my adapter. I already succeeded to display some informations from my JSON (codeLieu and libelle) that looks like this:
[
{
"codeLieu": "OTAG",
"libelle": "50 Otages",
"distance": null,
"ligne": [
{
"numLigne": "2"
},
{
"numLigne": "C2"
},
{
"numLigne": "12"
},
{
"numLigne": "23"
}
]
},
...
]
Here is my model:
package material.romain.com.projentreprise.Adapter;
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
import java.util.List;
public class Response implements Serializable{
private String codeLieu;
private String libelle;
private String distance;
private List<LigneEntities> ligne;
public String getCode() {
return codeLieu;
}
public void setCode(String codeLieu) {
this.codeLieu = codeLieu;
}
public String getLibelle() {
return libelle;
}
public void setLibelle(String libelle) {
this.libelle = libelle;
}
public String getDistance() {
return distance;
}
public void setDistance(String distance) {
this.distance = distance;
}
public List<LigneEntities> getLigne() {return ligne;}
public void setLigne(List<LigneEntities> ligne) {
this.ligne = ligne;
}
public static class LigneEntities {
private String numLigne;
public String getLigne() {
return numLigne;
}
public void setLigne(String numLigne) {
this.numLigne = numLigne;
}
}
}
And finally this is my adapter :
package material.romain.com.projentreprise.Adapter;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.support.v4.content.ContextCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;
import com.mikepenz.fontawesome_typeface_library.FontAwesome;
import com.mikepenz.iconics.IconicsDrawable;
import java.util.ArrayList;
import de.hdodenhof.circleimageview.CircleImageView;
import material.romain.com.projentreprise.R;
import material.romain.com.projentreprise.Util.CircularTextView;
import material.romain.com.projentreprise.Util.ColorLigne;
public class ListAdapter extends BaseAdapter implements Filterable {
private ArrayList<Response> arret;
private Context context;
private LayoutInflater inflater;
private MyFilter mFilter;
private ArrayList<Response> mSearchArret;
public ListAdapter(Context mContext, ArrayList<Response> mArretItem) {
this.context = mContext;
this.arret = mArretItem;
this.mSearchArret = mArretItem;
getFilter();
}
#Override
public int getCount() {
return mSearchArret.size();
}
#Override
public Object getItem(int position) {
return mSearchArret.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Response item = (Response) getItem(position);
ColorLigne.ViewHolder holder = null;
if (convertView == null) {
holder = new ColorLigne.ViewHolder();
inflater = LayoutInflater.from(context);
convertView = inflater.inflate(R.layout.each_list_item, parent, false);
holder.circleImage = (CircleImageView) convertView.findViewById(R.id.circleView);
holder.textArret = (TextView) convertView.findViewById(R.id.tvListArret);
holder.circle = (CircularTextView) convertView.findViewById(R.id.tvArretColor);
convertView.setTag(holder);
} else {
holder = (ColorLigne.ViewHolder) convertView.getTag();
}
Drawable color = new ColorDrawable(ContextCompat.getColor(context, R.color.tanVert));
Drawable image = new IconicsDrawable(context).icon(FontAwesome.Icon.faw_bus).color(Color.WHITE).sizeDp(48).paddingDp(10);
LayerDrawable ld = new LayerDrawable(new Drawable[]{color, image});
holder.circleImage.setImageDrawable(ld);
holder.textArret.setText(item.getLibelle());
return convertView;
}
#Override
public Filter getFilter() {
if (mFilter == null) {
mFilter = new MyFilter();
}
return mFilter;
}
class MyFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if (prefix != null && prefix.length() > 0) {
ArrayList<Response> tempList = new ArrayList<>();
for (Response value : arret) {
if (value.getLibelle().toLowerCase().contains(prefix.toString().toLowerCase())) {
tempList.add(value);
}
}
results.count = tempList.size();
results.values = tempList;
} else {
results.count = arret.size();
results.values = arret;
}
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
try {
mSearchArret = (ArrayList<Response>) results.values;
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
And I would like to get strings from "ligne" but it's in a list and I don't know how to access it. My goal is to put the strings into a circleTextView.
Edit:
I tried this in getView method
Response item = getItem(position);
for(Response value: arret){
value = item;
String ligneItem = value.getLigne().toString();
ColorLigne.setColorLigne(ligneItem, holder, context);
holder.circle.setText(ligneItem);
holder.circle.setStrokeWidth(0);
}
Add below method to your Response.java
public String getItems() {
StringBuilder builder = new StringBuilder();
for (LigneEntities entity : getLigne()) { //loop through every item from the list
builder.append(entity.getLigne() + ","); //add to StringBuilder
}
builder.replace(builder.length() - 1, builder.length(), "");//remove last ,(semicolon)
return builder.toString();
}
setting to your CircleTextView
holder.circle.setText(item.getItems());
I am a bit lost here,
I have a JSON string like this:
{
"type":"fuu",
"message":"bar",
"data":{
"5":{
"post":"foo",
"type":"bar",
},
"0":{
"post":"foo",
"type":"bar",
},
"1":{
"post":"foo",
"type":"bar",
},
// and so on...
}
}
Please how do I parse it into POJOs using Gson? (I need to get the list of objects)
I am a bit confused by the number in front of the elements of the list of objects....
Try this -
Pojo.java
import java.util.Map;
public class Pojo {
private String type;
private String message;
private Map<Integer, InnerPojo> data;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Map<Integer, InnerPojo> getData() {
return data;
}
public void setData(Map<Integer, InnerPojo> data) {
this.data = data;
}
#Override
public String toString() {
return "Pojo [type=" + type + ", message=" + message + ", data=" + data
+ "]";
}
}
InnerPojo.java
public class InnerPojo {
private String type;
private String post;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getPost() {
return post;
}
public void setPost(String post) {
this.post = post;
}
#Override
public String toString() {
return "InnerPojo [type=" + type + ", post=" + post + "]";
}
}
Main.java
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.testgson.beans.Pojo;
public class Main {
private static Gson gson;
static {
gson = new GsonBuilder().create();
}
public static void main(String[] args) {
String j = "{\"type\": \"fuu\", \"message\": \"bar\", \"data\":{ \"0\":{\"post\": \"foo\", \"type\": \"bar\"}, \"1\":{\"post\": \"foo\", \"type\": \"bar\"}, \"5\":{\"post\": \"foo\", \"type\": \"bar\"}}}";
Pojo p = gson.fromJson(j, Pojo.class);
System.out.println(p);
}
}
And Result is -
Pojo [type=fuu, message=bar, data={0=InnerPojo [type=bar, post=foo], 1=InnerPojo [type=bar, post=foo], 5=InnerPojo [type=bar, post=foo]}]
For the "data" part, I'd try to parse it into a Map<Integer, TypedPost> structure, see this thread for instructions.
We are using Jersey/Jackson to unmarshall JSON data to java DTOs. One of my DTO is an abstract class, and i would like to unmarshall the JSON data to one of his extended DTO. For example, assuming i have these DTOs :
public abstract class AnimalDTO{}
public class DogDTO extends AnimalDTO{}
public class CatDTO extends AnimalDTO{}
I would like to unmarshall this JSON data:
{Zoo: {Animals:[{"type"="DogDTO", "code"="001", "name"="chihuahua"}, {"type"="CatDTO", "code"="002", "name"="felix"}]}}
As "type" would give the type of DTO i would like to unmarshall to. But it seems that this property isn't considered. Is there something I missed, or mistook in the JSON syntax?
Thanks.
In your case you should use #JsonTypeInfo annotation.
For more information, please see below links:
JacksonFAQ.
Jackson 1.5: Polymorphic Type Handling, first steps.
Using above links I have created a simple example which serialize POJO objects with class names:
import java.io.StringWriter;
import java.util.Arrays;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonProgram {
public static void main(String[] args) throws Exception {
DogDTO dog = new DogDTO();
dog.setCode("001");
dog.setName("chihuahua");
CatDTO cat = new CatDTO();
cat.setCode("002");
cat.setName("felix");
Zoo zoo = new Zoo();
zoo.setAnimals(new AnimalDTO[] { dog, cat });
Data data = new Data();
data.setZoo(zoo);
ObjectMapper objectMapper = new ObjectMapper();
StringWriter writer = new StringWriter();
objectMapper.writeValue(writer, data);
System.out.println(writer);
}
}
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
abstract class AnimalDTO {
private String code;
private String name;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "AnimalDTO [code=" + code + ", name=" + name + "]";
}
}
class DogDTO extends AnimalDTO {
}
class CatDTO extends AnimalDTO {
}
class Zoo {
#JsonProperty(value = "Animals")
private AnimalDTO[] animals;
public AnimalDTO[] getAnimals() {
return animals;
}
public void setAnimals(AnimalDTO[] animals) {
this.animals = animals;
}
#Override
public String toString() {
return "Zoo [animals=" + Arrays.toString(animals) + "]";
}
}
class Data {
#JsonProperty(value = "Zoo")
private Zoo zoo;
public Zoo getZoo() {
return zoo;
}
public void setZoo(Zoo zoo) {
this.zoo = zoo;
}
#Override
public String toString() {
return "Data [zoo=" + zoo + "]";
}
}
This program prints:
{"Zoo":{"Animals":[{"type":"DogDTO","code":"001","name":"chihuahua"},{"type":"CatDTO","code":"002","name":"felix"}]}}