Arraylist Value object added to the JSON While using GSON - java

Hi in my app i am using to create a JSON string. So i thought of using GSON. I have two function one is to store the arraylist and another is normal object. My problem is the ArrayList part is working fine but when i print the normal object function the arraylist object is added to the json part here is my coding
main class
JsonStructure json = new JsonStructure();
json.messages.add("msg 1");
json.messages.add("msg 2");
json.messages.add("msg 3");
json.asecs.add("asec 1");
json.asecs.add("asec 2");
json.asecs.add("asec 3");
Gson gson = new Gson();
output = gson.toJson(json);
Log.i("gson", output);
List<JsonStructure> Allergylist = new ArrayList<JsonStructure>();
for (int i = 0; i < 5; i++) {
JsonStructure oAllergy_Data = new JsonStructure();
oAllergy_Data.setIdmember("hi");
oAllergy_Data.setIduser("hello");
// Adding register to list
Allergylist.add(oAllergy_Data);
}
Gson newgson = new Gson();
String newoutput = newgson.toJson(Allergylist);
Log.i("gson new", newoutput);
and here is my object class
public class JsonStructure {
String idpeople;
String iduser;
String idmember;
ArrayList<String> messages = new ArrayList<String>();
ArrayList<String> asecs = new ArrayList<String>();
public JsonStructure() {
}
public String getIdpeople() {
return idpeople;
}
public void setIdpeople(String idpeople) {
this.idpeople = idpeople;
}
public String getIduser() {
return iduser;
}
public void setIduser(String iduser) {
this.iduser = iduser;
}
public String getIdmember() {
return idmember;
}
public void setIdmember(String idmember) {
this.idmember = idmember;
}
public ArrayList<String> getMessages() {
return messages;
}
public void setMessages(ArrayList<String> messages) {
this.messages = messages;
}
public ArrayList<String> getAsecs() {
return asecs;
}
public void setAsecs(ArrayList<String> asecs) {
this.asecs = asecs;
}
}
my out put that look like
gson(21917): {"asecs":["asec 1","asec 2","asec 3"],"messages":["msg 1","msg 2","msg 3"]}
gson new(21917): [{"asecs":[],"idmember":"hi","iduser":"hello","messages":[]},{"asecs":[],"idmember":"hi","iduser":"hello","messages":[]},{"asecs":[],"idmember":"hi","iduser":"hello","messages":[]},{"asecs":[],"idmember":"hi","iduser":"hello","messages":[]},{"asecs":[],"idmember":"hi","iduser":"hello","messages":[]}]
my out put should look like
gson new(21917): [{"idmember":"hi","iduser":"hello"},{"idmember":"hi","iduser":"hello"},{"idmember":"hi","iduser":"hello"},{"idmember":"hi","iduser":"hello"},{"idmember":"hi","iduser":"hello"}]
my question is
1)If the gson will display all the object that declare in the class then why the idpeople is not display only arraylist is displayed to my json
2)Should i need to create a separate object file for the Arraylist or any alter coding for my coding

whatever the JsonStructure will contain, all that will be part of your json. if you dont want to include it in your json remove it from class.
I personally think it is not going to harm anyone if your json will contain any extra field and that field is useful for you.
Creating an new class -
JsonStructure oAllergy_Data = new JsonStructure();
will allow your arraylist to be a part of your json. if you dont want it to include, make it separate from JsonStructure class.
Or As an alternative Json can be created like this -
JSONObject outer = new JSONObject();
try {
// field
outer.put("EMAIL", reqModel.getEmail());
// field
outer.put("PASSWORD", reqModel.getPassword());
} catch (JSONException e) {
//
} catch (Exception e) {
//
}
return outer.toString();
remove this line
ArrayList<String> messages = new ArrayList<String>();
ArrayList<String> asecs = new ArrayList<String>();
Use
ArrayList<String> messages ;
ArrayList<String> asecs;
only

Related

Serialization of an Object having a polymorphic list of different type

I am trying to build a custom App to control Smart Home devices utilizing the Tasmota firmware and MQTT. Primarily that is smart lights at the moment. Therefore I have a Device class with children depending on the type of the device. Each device stores a DeviceState which is updated due to any changes made through the app. So the DeviceState is always the current state of the device. Depending on the device I need different DeviceStates, so again there is one superclass and subclass.
Now i want to store scenes with an ArrayList of DeviceStates to first store and than recreate certain light atmospheres. Therefore there is a class called Scene holding basic information and the described ArrayList.
To Store those lists i am using the Gson library in Android. My question is now how to be able to save those scenes objects with a polymorphic list inside.
I have followed this stackoverflow post: Gson serialize a list of polymorphic objects to save my devices as an Json String using the Gson library and a custom serializer / deserializer. But now Hence DeviceState doesn´t extend Scene I can´t use one serializer to create a String out of the Scene object. And if i would extend DeviceState to Scene, the DeviceState class would declare multiple JSON fields with the same name, because I am using "typeName" to differentiate those classes.
So basically i am getting the errors, that DeviceState doesn´t extend Scene or that DeviceState declares multiple JSON fields named "typeName".
public class Scene{
private ArrayList<DeviceState> states;
private String name;
private String room;
private String typeName;
public ArrayList<Scene> sceneList = new ArrayList<>();
public Scene(){
}
public Scene(String pName, String pRoom) {
name = pName;
room = pRoom;
states = new ArrayList<>();
typeName = "Scene";
}
public String getName() {
return name;
}
public String getRoom() {
return room;
}
public void addDevice(Device d) {
states.add(d.getState());
}
public void execute() {
System.out.println(states.size());
}
public String getTypeName(){
return typeName;
}
}
public class DeviceState {
private String typeName;
private String deviceTopic;
public static final String RGBWLightState = "RGBWLightState";
public static final String Default = "DeviceState";
public DeviceState(String pTypeName, String pDeviceTopic){
typeName = pTypeName;
deviceTopic = pDeviceTopic;
}
public DeviceState(){
typeName = Default;
}
public String getTypeName() {
return typeName;
}
}
public class CustomSceneSerializer implements JsonSerializer<ArrayList<Scene>> {
private static Map<String, Class> map = new TreeMap<>();
static {
map.put(DeviceState.RGBWLightState, RGBWLightState.class);
map.put(DeviceState.Default, DeviceState.class);
map.put("Scene", Scene.class);
}
#Override
public JsonElement serialize(ArrayList<Scene> src, Type typeOfSrc, JsonSerializationContext context) {
if(src == null) {
return null;
}else{
JsonArray ja = new JsonArray();
for(Scene s : src){
Class c = map.get(s.getTypeName());
if(c == null){
throw new RuntimeException("Unkown class: " + s.getTypeName());
}
ja.add(context.serialize(s, c));
}
return ja;
}
}
}
public class CustomSceneDeserializer implements JsonDeserializer<List<Scene>> {
private static Map<String, Class> map = new TreeMap<>();
static {
map.put(DeviceState.RGBWLightState, RGBWLightState.class);
map.put(DeviceState.Default, DeviceState.class);
map.put("Scene", Scene.class);
}
#Override
public List<Scene> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
ArrayList list = new ArrayList<Scene>();
JsonArray ja = json.getAsJsonArray();
for (JsonElement je : ja) {
String type = je.getAsJsonObject().get("typeName").getAsString();
Class c = map.get(type);
if (c == null)
throw new RuntimeException("Unknow class: " + type);
list.add(context.deserialize(je, c));
}
return list;
}
}
To save the Object holding a list of those objects I am using:
String json = preferences.getString("scene_holder", "");
GsonBuilder gb = new GsonBuilder();
List<Scene> al = new ArrayList<>();
gb.registerTypeAdapter(al.getClass(), new CustomSceneDeserializer());
gb.registerTypeAdapter(al.getClass(), new CustomSceneSerializer());
Gson gson = gb.create();
System.out.println(list.size());
list.get(0).execute();
System.out.println(json);
if (!(json.equals(""))) {
Scene result = gson.fromJson(json, Scene.class);
System.out.println(result.sceneList.size());
result.sceneList = list;
System.out.println(result.sceneList.size());
editor.putString("scene_holder", gson.toJson(result)).commit();
} else {
Scene scene = new Scene();
scene.sceneList = list;
editor.putString("scene_holder", gson.toJson(scene)).commit();
}

Gson- Parsing a JSON array of JSON objects to ArrayList<org.json.JSONObject>

I have a JSON string like this:
{
"r": [
{
"pic": "1.jpg",
"name": "Name1"
},
{
"pic": "2.jpg",
"name": "Name2"
},
{
"pic": "3.jpg",
"name": "Name3"
}
]
}
I want to parse to this POJO model:
public class Catalog {
#SerializedName("r")
#Expose
private List<JSONObject> r = new ArrayList<JSONObject>();
public List<JSONObject> getR() {
return r;
}
public void setR(List<JSONObject> r) {
this.r = r;
}
}
I am parsing this way:
Catalog cat = new Gson().fromJson(jsonString,Catalog.class);
But finally am getting this json
{
"r": [
{
"nameValuePairs": {}
},
{
"nameValuePairs": {}
},
{
"nameValuePairs": {}
}
]
}
Please note that I don't want to use com.google.gson.JsonObject.
I want to use org.json.JSONObject. How to achieve this because almost all of my code uses it?
As it was already mentioned in other answer and comments, you probably might not really want to use org.json.JSONObject for several reasons. But if it's a must for you, you just have to create your org.json.JSONObject-aware Gson instance.
final class JSONObjectJsonDeserializer
implements JsonDeserializer<JSONObject> {
// The implementation is fully thread-safe and can be instantiated once
private static final JsonDeserializer<JSONObject> jsonObjectJsonDeserializer = new JSONObjectJsonDeserializer();
// Type tokens are immutable values and therefore can be considered constants (and final) and thread-safe as well
private static final TypeToken<Map<String, Object>> mapStringToObjectTypeToken = new TypeToken<Map<String, Object>>() {
};
private JSONObjectJsonDeserializer() {
}
static JsonDeserializer<JSONObject> getJsonObjectJsonDeserializer() {
return jsonObjectJsonDeserializer;
}
#Override
public JSONObject deserialize(final JsonElement jsonElement, final Type type, final JsonDeserializationContext context) {
// Convert the input jsonElement as if it were a Map<String, Object> (a generic representation for JSON objectS)
final Map<String, Object> map = context.deserialize(jsonElement, mapStringToObjectTypeToken.getType());
// And forward the map to the JSONObject constructor - it seems to accept it nice
return new JSONObject(map);
}
}
Gson is designed thread-safe and does not need to be instantiated every time serialization or deserialization is necessary:
private static final Gson gson = new GsonBuilder()
.registerTypeAdapter(JSONObject.class, getJsonObjectJsonDeserializer())
.create();
And finally:
final Catalog catalog = gson.fromJson(jsonString, Catalog.class);
out.println(catalog.getR());
with the following result:
[{"name":"Name1","pic":"1.jpg"}, {"name":"Name2","pic":"2.jpg"}, {"name":"Name3","pic":"3.jpg"}]
Anyway, I would suggest you to redesign your mappings model.
I think you don't need JSONObject.
Try this
// is wrapped class for serialized json.
public class JsonExample
{
List<Catalog> r;
}
public class Catalog {
private String pic;
private String name;
public String getPic() {
return pic;
}
public String getName() {
return name;
}
}
JsonExample example = new Gson().fromJson(json, JsonExample.class);
Additional - using JSONObject
JSONObject obj = new JSONObject(json);
JSONArray arr = obj.getJSONArray("r");
List<Catalog> cataList = new ArrayList<>();
for(int i = 0 ; i < arr.length() ; ++i)
{
cataList.add(new Catalog(arr.getJSONObject(i)));
}
public class Catalog {
private String pic;
private String name;
public Catalog(JSONObject obj) throws JSONException
{
pic = obj.getString("pic");
name = obj.getString("name");
}
public String getPic() {
return pic;
}
public String getName() {
return name;
}
}
I think in your case, usage of gson library is not required at all.
Only org.json can solve the entire problem.
E.g.:
JSONObject json = new JSONObject(jsonString);
JSONArray jsonArray = json.getJSONArray("r");
List<JSONObject> jsonList = new ArrayList<>();
for (int i = 0; i < jsonArray.length(); i++) {
jsonList.add(jsonArray.getJSONObject(i));
}
Catalog catalog = new Catalog();
catalog.setR(jsonList);

Convert ArrayList of custom objects to JSON

I have an ArrayList of custom Objects. Each of these objects have an arraylist of another custom object. Then these second level of custom objects have an arraylist of another custom object.
This is how the class hierarchy looks like
public class Undle {
private String undleStatus;
private ArrayList<ArcelFolder> arcelFolders;
public ArrayList<ArcelFolder> getArcelFolders() {
return arcelFolders;
}
public void setArcelFolders(ArrayList<ArcelFolder> arcelFolders) {
this.arcelFolders = arcelFolders;
}
//Other getter and setters
}
public class ArcelFolder {
private ArrayList<ArcelDocument> arcelDocuments;
private String arcelStatus;
public String getArcelStatus() {
return arcelStatus;
}
public void setArcelStatus(String arcelStatus) {
this.arcelStatus = arcelStatus;
}
public ArrayList<ArcelDocument> getArcelDocuments() {
return arcelDocuments;
}
public void setArcelDocuments(ArrayList<ArcelDocument> arcelDocuments) {
this.arcelDocuments = arcelDocuments;
}
}
public class ArcelDocument {
private String gain;
public String getGain() {
return gain;
}
public void setGain(String gain) {
this.gain = gain;
}
}
I have an arraylist of Undle objects
ArrayList<Undle> undleList = new ArrayList<Undle>();
// Create objects of ArcelFolder and ArcelDocument
// Add ArcelDocument list to ArcelFolder
// Add ArcelFolder list to Undle arraylist
I would like to convert Undle ArrayList to a JSON. How can I flatten this hierarcical structure of beans and put it in a JSON?
I tried doing something like
org.json.simple.JSONObject resultObj = new JSONObject(undleList);
and
org.json.simple.JSONArray arr = new JSONArray(undleList);
But it seems that they work only if a String ArrayList is passed.
Gson gson = new Gson();
Type type = new TypeToken<List<Bundle>>() {}.getType();
String json = gson.toJson(bundleList, type);
System.out.println(json);
List<Bundle> fromJson = gson.fromJson(json, type);
for (Bundle bundle : fromJson) {
System.out.println(bundle);
}

How to generate Json with Java

I am working on an application where i have to generate a json like this:
[
{"title":"Culture","start":"Salary","end":"Work"},
{"title":"Work","start":"Salary","end":"Work"}
]
But my code generates json like this:
{{"name":"Culture"},[{"name":"Salary"},{"name":"Work"}],}
My code:
public class ParseJson {
public static class EntryListContainer {
public List<Entry> children = new ArrayList<Entry>();
public Entry name;
}
public static class Entry {
private String name;
public Entry(String name) {
this.name = name;
}
}
public static void main(String[] args) {
EntryListContainer elc1 = new EntryListContainer();
elc1.name = new Entry("Culture");
elc1.children.add(new Entry("Salary"));
elc1.children.add(new Entry("Work"));
ArrayList<EntryListContainer> al = new ArrayList<EntryListContainer>();
Gson g = new Gson();
al.add(elc1);
StringBuilder sb = new StringBuilder("{");
for (EntryListContainer elc : al) {
sb.append(g.toJson(elc.name));
sb.append(",");
sb.append(g.toJson(elc.children));
sb.append(",");
}
String partialJson = sb.toString();
if (al.size() > 1) {
int c = partialJson.lastIndexOf(",");
partialJson = partialJson.substring(0, c);
}
String finalJson = partialJson + "}";
System.out.println(finalJson);
}
}
Can anyone help me to generate this json in my required format ?? please thanks in advance
Try this
public class Entry {
public String title;
public String start;
public String end;
}
And in another part of your code
private ArrayList<Entry> entries = new ArrayList<>();
// Fill the entries...
String the_json = new Gson().toJson(entries);
1) First Create your POJO
public class MyJSONObject {
private String title;
private String start;
private String end;
//getter and setter methods
[...]
#Override
public String toString() {
}
}
2) Use com.google.code.gson library
public static void main(String[] args) {
{
ArrayList<MyJSONObject> myJSONArray = new ArrayList<>();
MyJSONObject obj = new MyJSONObject();
obj.setTitle="Culture";
obj.set[...]
myJSONArray.add(obj);
Gson gson = new Gson();
// convert java object to JSON format,
// and returned as JSON formatted string
String json = gson.toJson(myJSONArray);
System.out.println(json);
}
Output : [{"title":"Culture","start":"Salary","end":"Work"}, ...]
I recommend you to use some JSON Java API, like Gson. It's very simple to generate a string json from a POJO object or to create a POJO object from a string json.
The code for generating a string json from a POJO object is like this:
Gson gson = new Gson();
String stringJson = gson.toJson(somePojoObject);
The code for creating a POJO object from a string json is like this:
Gson gson = new Gson();
SomePojoClass object = gson.fromJson(stringJson, SomePojoClass.class);
Note that you can not serialize objects with circular references. This causes infinite recursion.

Mask value of selected key in JSON

I have JSON request and response, I want to print the JSONs in the log, but there are some secured fields which I want to avoid to print in the log, I am trying to mask fields keys:
example:
before masking:
{"username":"user1","password":"123456","country":"US","creditCardNumber":"1283-1238-0458-3458"}
after masking
{"username":"user1","password":"XXXXXX","country":"US","creditCardNumber":"XXXXXX"}
I am using java Gson lib, please help me to do that
EDIT
I want to pass the keys dynamically, so in function a I want to mask these fields, but in function b different fields.
I think you should exclude that fields from log. Below is a simple example using Gson and #Expose annotation.
public static void main(String[] args) throws IOException {
String json = "{\"username\":\"user1\",\"password\":\"123456\",\"country\":\"US\",\"creditCardNumber\":\"1283-1238-0458-3458\"}";
Gson gson = new Gson();
User user = gson.fromJson(json, User.class);
System.out.println(gson.toJson(user));
Gson gsonExpose = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
System.out.println(gsonExpose.toJson(user));
}
public class User {
#Expose
private String username;
private String password;
#Expose
private String country;
private String creditCardNumber;
}
Output will be:
{"username":"user1","password":"123456","country":"US","creditCardNumber":"1283-1238-0458-3458"}
{"username":"user1","country":"US"}
Another solution using Reflection:
public static void main(String[] args) throws IOException {
String json = "{\"username\":\"user1\",\"password\":\"123456\",\"country\":\"US\",\"creditCardNumber\":\"1283-1238-0458-3458\"}";
Gson gson = new Gson();
User user = gson.fromJson(json, User.class);
List<String> fieldNames = Arrays.asList("password", "creditCardNumber");
System.out.println(mask(user, fieldNames, "XXXXXXX"));
}
public static String mask(Object object, List<String> fieldNames, String mask) {
Field[] fields = object.getClass().getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
if (fieldNames.contains(fields[i].getName())) {
try {
fields[i].setAccessible(true);
if (fields[i].get(object) != null) {
fields[i].set(object, mask);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Gson gson = new Gson();
return gson.toJson(object);
}
I like the above solution to mask using reflection but wanted to extend same for other field types and saving masked field to unmask again.
Create annotation #MaskedField on top of field.
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface MaskedField {
}
public <T> Map<String,? super Object> maskObjectFields(T object){
Map<String,? super Object> values = new HashMap<>();
Arrays.stream(object.getClass().getDeclaredFields()).filter(field->null != field.getAnnotation(MaskedField.class)).
forEach(annotatedField->{
try {
if(annotatedField.getType().isAssignableFrom(String.class)) {
annotatedField.setAccessible(true);
values.put(annotatedField.getName(),annotatedField.get(object));
annotatedField.set(object, maskString((String) annotatedField.get(object)));
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
});
return values;
}
public <T> void unMaskObjectFields(T object,Map values){
Arrays.stream(object.getClass().getDeclaredFields()).filter(field->null != field.getAnnotation(MaskedField.class)).
forEach(annotatedField->{
try {
annotatedField.setAccessible(true);
annotatedField.set(object,values.get(annotatedField.getName()));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
});
}
private String maskString(String value){
if(Objects.isNull(value)) return null;
return null; //TODO: your logic goes here for masking
}

Categories

Resources