Is it possible to convert jsonobject code to a java object just using JDK and without other libraries like Gson or jackson? Trying to convert the code below to work without JSON.
public void run(){
boolean flag = true;
while (flag){
try {
JsonObject jsonObject = Json.createReader(bufferedReader).readObject();
if(jsonObject.containsKey("userID"))
System.out.println("["+jsonObject.getString("userID")+"]: "+jsonObject.getString("message"));
} catch (Exception e) {
flag = false;
interrupt();
}
} //while loop brackets
}
I think I found an answer:
Created a global variable string array
private String[] address;
and then corrected the code. I think this will work, will troubleshoot later.
boolean flag = true;
while (flag){
try {
Object o = new BufferedReader(bfr).readLine(); /** MIGHT BE PROBLEMS HERE **/
if(o.equals(address)) /** From here **/
System.out.println("["+o.toString()+"]: "+o.toString());
/** To here**/
} catch (Exception e) {
flag = false;
interrupt();
}
} //while loop brackets
} // run brackets```
Create a new class with 2 String attributes, then create a new instance with your json object.
public class MyObject() {
private String attribute1;
private String attribute2;
public MyObject(String s1, String s2) {
attribute1 = s1;
attribute2 = s2;
}
}
MyObject myObj = new MyObject(jsonObjec.getString("userID"),jsonObjec.getString("message"));
To use it in a loop simple create an array (or ArrayList) of that type :
ArrayList<MyObject> objects = new ArrayList<>();
In your loop :
objects.add(new MyObject(jsonObjec.getString("userID"),jsonObjec.getString("message")));
Related
I have requirement where I need to convert java object to json.
I am using Gson for that but i need the converter to only serialize the non null or not empty values.
For example:
//my java object looks like
class TestObject{
String test1;
String test2;
OtherObject otherObject = new OtherObject();
}
now my Gson instance to convert this object to json looks like
Gson gson = new Gson();
TestObject obj = new TestObject();
obj.test1 = "test1";
obj.test2 = "";
String jsonStr = gson.toJson(obj);
println jsonStr;
In the above print, the result is
{"test1":"test1", "test2":"", "otherObject":{}}
Here i just wanted the result to be
{"test1":"test1"}
Since the test2 is empty and otherObject is empty, i don't want them to be serialized to json data.
Btw, I am using Groovy/Grails so if there is any plugin for this that would be good, if not any suggestion to customize the gson serialization class would be good.
Create your own TypeAdapter
public class MyTypeAdapter extends TypeAdapter<TestObject>() {
#Override
public void write(JsonWriter out, TestObject value) throws IOException {
out.beginObject();
if (!Strings.isNullOrEmpty(value.test1)) {
out.name("test1");
out.value(value.test1);
}
if (!Strings.isNullOrEmpty(value.test2)) {
out.name("test2");
out.value(value.test1);
}
/* similar check for otherObject */
out.endObject();
}
#Override
public TestObject read(JsonReader in) throws IOException {
// do something similar, but the other way around
}
}
You can then register it with Gson.
Gson gson = new GsonBuilder().registerTypeAdapter(TestObject.class, new MyTypeAdapter()).create();
TestObject obj = new TestObject();
obj.test1 = "test1";
obj.test2 = "";
System.out.println(gson.toJson(obj));
produces
{"test1":"test1"}
The GsonBuilder class has a bunch of methods to create your own serialization/deserialization strategies, register type adapters, and set other parameters.
Strings is a Guava class. You can do your own check if you don't want that dependency.
What I personally don't like in TypeAdapter using answer is the fact you need to describe every field of your entire class which could have lets say 50 fields (which means 50 if blocks in TypeAdapter).
My solution is based on Reflection and a fact Gson will not serialize null values fields by default.
I have a special class which holds data for API to create document called DocumentModel, which has about 50 fields and I don't like to send String fields with "" (empty but not null) values or empty arrays to server. So I created a special method which returns me a copy of my object with all empty fields nulled. Note - by default all arrays in my DocumentModel instance are initialized as empty (zero length) arrays and thus they are never null, you should probably check your arrays for null before checking their length.
public DocumentModel getSerializableCopy() {
Field fields[] = new Field[]{};
try {
// returns the array of Field objects representing the public fields
fields = DocumentModel.class.getDeclaredFields();
} catch (Exception e) {
e.printStackTrace();
}
DocumentModel copy = new DocumentModel();
Object value;
for (Field field : fields) {
try {
value = field.get(this);
if (value instanceof String && TextUtils.isEmpty((String) value)) {
field.set(copy, null);
// note: here array is not being checked for null!
else if (value instanceof Object[] && ((Object[]) value).length == 0) {
field.set(copy, null);
} else
field.set(copy, value);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return copy;
}
Using this method I don't care if some fields was added or removed after this method was written or whatever. The only problem left - is checking custom type fields, which are not String or array, but this depends to particular class and should be extra coded in if/else blocks.
It seems to me the problem is not with gson. Gson correctly keeps track of the difference between null and an empty string. Are you sure you want to erase that distinction? Are you sure all classes that use TestObject don't care?
What you could do if you don't care about the difference is to change the empty strings to null within a TestObject before serializing it. Or better, make the setters in TestObject such that an empty string is set to null; that way you define rigidly within the class that an empty string is the same as null. You'll have to make sure the values cannot be set outside the setters.
I have ran into the same problem and found 2 distinct solutions
Write a custom TypeAdapter for each field class
TypeAdapter example for String class:
#SuppressWarnings("rawtypes")
public class JSONStringAdapter extends TypeAdapter {
#Override
public String read(JsonReader jsonReader) throws IOException {
String value = jsonReader.nextString();
if(value == null || value.trim().length() == 0) {
return null;
} else {
return value;
}
}
#Override
public void write(JsonWriter jsonWriter, Object object) throws IOException {
String value = String.valueOf(object);
if(value == null || value.trim().length() == 0) {
jsonWriter.nullValue();
} else {
jsonWriter.value(value);
}
}
}
Use:
public class Doggo {
#JsonAdapter(JSONStringAdapter.class)
private String name;
public Doggo(String name) {
this.name = name;
}
}
public class Main {
public static void main(String[] args) {
Doggo aDoggo = new Doggo("");
String jsonString = new Gson().toJson(aDoggo);
}
}
Process the object manually before generating the JSON string
Seems to work on anything, haven't tested the performance:
public static boolean removeEmpty(JSONObject source) {
if (null == source || source.length() == 0) {
return true;
}
boolean isJsonObjectEmpty = false;
for (String key : JSONObject.getNames(source)) {
Object value = source.get(key);
boolean isValueEmpty = isValueEmpty(value);
if(isValueEmpty) {
source.remove(key);
}
}
if(source.length() == 0) {
isJsonObjectEmpty = true;
}
return isJsonObjectEmpty;
}
private static boolean isValueEmpty(Object value) {
if (null == value) {
return true;
}
if (value instanceof JSONArray) {
JSONArray arr = (JSONArray) value;
if(arr.length() > 0) {
List<Integer> indextesToRemove = new ArrayList<>();
for(int i = 0; i< arr.length(); i++) {
boolean isValueEmpty = isValueEmpty(arr.get(i));
if(isValueEmpty) {
indextesToRemove.add(i);
};
}
for(Integer index : indextesToRemove) {
arr.remove(index);
}
if(arr.length() == 0) {
return true;
}
} else {
return true;
}
} else if (value instanceof JSONObject) {
return removeEmpty((JSONObject) value);
} else {
if (JSONObject.NULL.equals(value)
|| null == value
|| value.toString().trim().length() == 0)
) {
return true;
}
}
return false;
}
Use:
public class Doggo {
private String name;
public Doggo(String name) {
this.name = name;
}
}
public class Main {
public static void main(String[] args) {
Doggo aDoggo = new Doggo("");
// if you are not using Type Adapters for your fields
JSONObject aJSONObject1 = new JSONObject(aDoggo);
removeEmpty(aJSONObject1);
String jsonString1 = aJSONObject1.toString();
// if you are using Type Adapters for your fields
Gson gsonParser = new Gson();
JSONObject aJSONObject2 = new JSONObject(gsonParser .toJson(aDoggo));
removeEmpty(aJSONObject2);
String jsonString2 = aJSONObject2.toString();
}
}
Is it possible to make library classes comparable without extending them?
import org.json.JSONObject;
LinkedList<JSONObject> list = getListFromFunction();
TreeSet<JSONObject> treeSet = new TreeSet<JSONObject>(list);
Making a TreeSet here is not possible as JSONObject is not comparable. How can I "attach" a custom comparator to JSONObject? (There is a unique property, say "_some_id" to compare with)
We can use Comparator in such a case and handle the scenario. Please refer the below example.
Main Class
public class ComparatorTest{
public static void main(String[] ar) {
// System.out.println(new Sample().stringTimes("vivek", 5));
JSONObject emp1 = new JSONObject();
JSONObject emp2 = new JSONObject();
try {
emp1.put("department", "IT");
emp1.put("name", "bvivek");
emp1.put("id", 1);
emp2.put("department", "IT");
emp2.put("name", "avikash");
emp2.put("id", 2);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
List<JSONObject> employess = new ArrayList<JSONObject>();
employess.add(emp1);//add to list
employess.add(emp2);//add to list
System.out.println(employess);//unsorted, as is
Collections.sort(employess, new JSONComparator("name"));
System.out.println(employess);//sorted as per the field
//using treeSet
TreeSet<JSONObject> jsonInTree = new TreeSet<JSONObject>(new JSONComparator("id"));
jsonInTree.addAll(employess);
System.out.println(jsonInTree);//using the tree implementation
}
}
JSONComparator
class JSONComparator implements Comparator<JSONObject> {
private String fieldToCompare;
public JSONComparator(String fieldToCompare) {
this.fieldToCompare = fieldToCompare;
}
#Override
public int compare(JSONObject o1, JSONObject o2) {
String id1 = "";
String id2 = "";
try {
id1 = o1.getString(this.fieldToCompare);
id2 = o2.getString(this.fieldToCompare);
} catch (JSONException e) {
}
return id1.compareTo(id2);
}
}
The simplest way to do something like this will work for any classes that aren't comparable. The way you do this is by creating your own comparing method, you can do this in a way like:
public static int compareJSONObjects(JSONObject obj1, JSONObject obj2){
if(obj1.getField()>obj2.getField()){
return 1;
}else{
return -1;
}
}
now when you call list.sort() you can create your own Comparator like this:
list.sort( (obj1, obj2) -> compareJSONObject(obj1, obj2) );
by doing this you cut down on the amount of lines required, as this entire thing could be shortened to 1 line by using ternary and doing:
list.sort( (obj1, obj2) -> obj1.getField()>obj2.getField() ? 1 : -1 );
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
I'm trying to use flexjson to deserialize a string I get from a web call. The problem is that a few elements in there have a dot in the property/key for example:
[{...
"contact.name": "Erik Svensson",
"contact.mail": "erik.svensson#foo.bar",
"contact.phone": "0731123243",
...}]
Now everything else falls in place except these strings with the dots, they end up null in my target class. I'm guessing it's because it doesn't know what to map them to as I can't declare a variable in my container class that has a dot.
This is the code I'm runnign to deserialize now,
mData = new JSONDeserializer<List<Thing>>()
.use("values", Thing.class)
.deserialize(reader);
How do I modify this to catch the strings with the dot and put them in my Things class as:
String contactName;
String contactMail;
String contactPhone;
// getters&setters
Note I don't have any control over the Serialization..
OK So I've solved this but I had to abandon flexJson. Searched all over the place for a simple way but couldn't find one.
Instead I went with Jackson and this is what I ended up with:
ObjectMapper mapper = new ObjectMapper();
mThings = mapper.readValue(url, new TypeReference<List<Thing>>() {});
And in my class Thing:
#JsonProperty("contact.name")
private String contactName;
#JsonProperty("contact.mail")
private String contactMail;
#JsonProperty("contact.phone")
private String contactPhone;
// getters and setters..
If anyone knows how to do this with FlexJson feel free to post an answer, I would like to see it.
As I was curious, too, if this type of assignment can be done easily, I've played with some code, and this is what I came up with. (I'm posting it here because maybe it's helpful for somebody having some related question, or just as a point to start from.)
The PrefixedObjectFactory (see below) will cut off a fixed prefix from the JSON object's field name and use this name to find a matching bean property. The code can be easily changed to do a replacement instead (e.g. setting the first letter after a . to uppercase and remove the .)
It can be used like this:
List<Thing> l = new JSONDeserializer<List<Thing>>().use("values", new PrefixedObjectFactory(Thing.class, "contact.")).deserialize(source);
The code:
import flexjson.ObjectBinder;
import flexjson.ObjectFactory;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Type;
import java.util.Map;
public class PrefixedObjectFactory<T> implements ObjectFactory {
protected Class<T> clazz;
protected String prefix;
public PrefixedObjectFactory(Class<T> c, String prefix) {
this.clazz = c;
this.prefix = (prefix == null) ? "" : prefix;
}
#Override
public Object instantiate(ObjectBinder context, Object value, Type targetType, Class targetClass) {
try {
Class useClass = this.clazz;
T obj = (T)useClass.newInstance();
if (value instanceof Map) {
// assume that the value is provided as a map
Map m = (Map)value;
for (Object entry : m.entrySet()) {
String propName = (String)((Map.Entry)entry).getKey();
Object propValue = ((Map.Entry)entry).getValue();
propName = fixPropertyName(propName);
propValue = fixPropertyValue(propValue);
assignValueToProperty(useClass, obj, propName, propValue);
}
} else {
// TODO (left out here, to keep the code simple)
return null;
}
return obj;
} catch (Exception ex) {
return null;
}
}
protected String fixPropertyName(String propName) {
if (propName.startsWith(this.prefix)) {
propName = propName.substring(this.prefix.length());
}
return propName;
}
protected Object fixPropertyValue(Object propValue) {
return propValue;
}
protected PropertyDescriptor findPropertyDescriptor(String propName, Class clazz) {
try {
return new PropertyDescriptor(propName, clazz);
} catch (Exception ex) {
return null;
}
}
protected void assignValueToProperty(Class clazz, Object obj, String propName, Object propValue) {
try {
PropertyDescriptor propDesc = findPropertyDescriptor(propName, clazz);
if (propDesc != null) {
propDesc.getWriteMethod().invoke(obj, propValue);
}
} catch (Exception ex) {
}
}
}
I have a ArrayList with custom objects. I want to search inside this ArrayList for Strings.
The class for the objects look like this:
public class Datapoint implements Serializable {
private String stateBased;
private String name;
private String priority;
private String mainNumber;
private String groupadress;
private String dptID;
public Datapoint(){
}
public String getMainNumber() {
return mainNumber;
}
public void setMainNumber(String mainNumber) {
this.mainNumber = mainNumber;
}
public String getName() {
return name;
}
..and so on
I know how to search for a string in a ArrayList but how to do that in a ArrayList with my custom objects:
ArrayList<String> searchList = new ArrayList<String>();
String search = "a";
int searchListLength = searchList.size();
for (int i = 0; i < searchListLength; i++) {
if (searchList.get(i).contains(search)) {
//Do whatever you want here
}
}
So I want to have a function to search in my ArrayList with for example five objects for all "name" strings.
The easy way is to make a for where you verify if the atrrtibute name of the custom object have the desired string
for(Datapoint d : dataPointList){
if(d.getName() != null && d.getName().contains(search))
//something here
}
I think this helps you.
UPDATE: Using Java 8 Syntax
List<DataPoint> myList = new ArrayList<>();
//Fill up myList with your Data Points
List<DataPoint> dataPointsCalledJohn =
myList
.stream()
.filter(p-> p.getName().equals(("john")))
.collect(Collectors.toList());
If you don't mind using an external libaray - you can use Predicates from the Google Guava library as follows:
class DataPoint {
String name;
String getName() { return name; }
}
Predicate<DataPoint> nameEqualsTo(final String name) {
return new Predicate<DataPoint>() {
public boolean apply(DataPoint dataPoint) {
return dataPoint.getName().equals(name);
}
};
}
public void main(String[] args) throws Exception {
List<DataPoint> myList = new ArrayList<DataPoint>();
//Fill up myList with your Data Points
Collection<DataPoint> dataPointsCalledJohn =
Collections2.filter(myList, nameEqualsTo("john"));
}
try this
ArrayList<Datapoint > searchList = new ArrayList<Datapoint >();
String search = "a";
int searchListLength = searchList.size();
for (int i = 0; i < searchListLength; i++) {
if (searchList.get(i).getName().contains(search)) {
//Do whatever you want here
}
}
Probably something like:
ArrayList<DataPoint> myList = new ArrayList<DataPoint>();
//Fill up myList with your Data Points
//Traversal
for(DataPoint myPoint : myList) {
if(myPoint.getName() != null && myPoint.getName().equals("Michael Hoffmann")) {
//Process data do whatever you want
System.out.println("Found it!");
}
}
For a custom class to work properly in collections you'll have to implement/override the equals() methods of the class. For sorting also override compareTo().
See this article or google about how to implement those methods properly.
contains() method just calls equals() on ArrayList elements, so you can overload your class's equals() based on the name class variable. Return true from equals() if name is equal to the matching String. Hope this helps.
Use Apache CollectionUtils:
CollectionUtils.find(myList, new Predicate() {
public boolean evaluate(Object o) {
return name.equals(((MyClass) o).getName());
}
}
String string;
for (Datapoint d : dataPointList) {
Field[] fields = d.getFields();
for (Field f : fields) {
String value = (String) g.get(d);
if (value.equals(string)) {
//Do your stuff
}
}
}
boolean found;
for(CustomObject obj : ArrayOfCustObj) {
if(obj.getName.equals("Android")) {
found = true;
}
}