I would like not to define an extra type just to make the json conversion. I am using a library that needs an object as an input and then performs http operations with this data, so I cannot use a hard coded json string as input.
private static final Gson GSON = new Gson();
public static void main(String[] args) {
System.out.println(GSON.toJson(new Object() {
private String email_address = "me#mail.eu";
public String getEmail_address() {return "me#mail.eu"; }
public void setEmail_address(String mail) {email_address = mail; }
}));
}
I tried to remove getter and setter or leave the getter and remove the field but it doesn't work. Anybody knows how to fix this?
Libraries for Json serialization/deseralization like Gson, count on the fact that you have defined your custom object on which you will map the json string. This is because they use reflection on the class to map the fields with the corresponding keys in the json. Without it, it is difficult that they can achieve anything(usable).
Why not define an extra type ? We are not in the 1980s. I would personnally use a DTO. What is Data Transfer Object?
But maybe the answer to you question reside here : Java - Does Google's GSON use constructors?
Related
I have list of json List<String> and each string have json like this {"id":"22","name":"Name","order":"1"} And I want to fetch it to list of input box then when I save it I
I want to take all changing and convert them to JSON
#ManagedBean
#ViewScoped
public class LiveStreamController extends ProductController implements Serializable {
private static final long serialVersionUID = 5037909267669512508L;
private static final Logger LOGGER = LoggerFactory.getLogger(LiveStreamController.class);
private LiveStream liveStream;
....
}
public class LiveStream extends Product implements Serializable {
private List<String> jsons = new ArrayList<>();
...
}
and I wanna read it
<c:forEach items="#{liveStreamController.liveStream.jsons}"
var="json ">
<h:outputFormat value="#{json.name}" />
<p:inputText value="#{json.order}" />
</c:forEach>
Effectively you are not asking a JSF question but an EL question since the #{json.name} expression is just that... Expression Language.
About the 'issue'...
If the value of the var="json" is a String, which it in your case is, it will be resolved by the basic resolvers that will for sure know about a String. An attempt will be made to call the property name on the string via a getName() which obviously does not exist, resulting in a Property 'name' not found on type java.lang.String. All of this is also explained in Property 'someproperty' not found on type java.lang.String. Therefor using it like in your example will not work
About the solution(s) for reading...
There are basically 3 solutions for reading the JSON and displaying it
New String EL Resolver
You could create a custom EL resolver and put it first in the order of resolvers so that for every string that needs to be resolved checks if it is effectively JSON (minimally parsing it) and if you think it IS JSON, then parse the JSON fully and read/interpret the EL and try to apply it to the JSON object. All this is going to be rather expensive as far as I can see (but BalusC might have a different idea)
New JSON EL Resolver
The second, a little better solution, is converting the String to a JSON object of you choice (there are many in Java, including a standardized one, 'JSON-P', since Java EE 7 and a newer version for Java EE 8). There is as far as I know no default included EL resolver that knows how to handle these in EL, but examples exist for the non standardized EL formats No idea how this would perform though, testing is knowing.
Existing EL Resolver
The third option is to convert the JSON to Normally strongly typed objects and then have the normal existing resolvers act on them. This can be Default existing java types like Map, List, String and other normal values, but it could even be more strongly typed like Person , Order, Converting JSON Strings to strongly typed object was a feature that existed in the non-standardized JSON libraries but not in default Java(EE) until Java EE 8, JSON-B. This has an additional advantage that code completion works and validations work in an IDE
About the solution(s) for writing...
Since you do seem to wanting to write results back to the JSON String (you have an input in your example), the first solution for reading is very hard to extend to writing, and if possible, it would totally break the advantage you seem to want to get of not writing code to be able to use this. The second and third solution both might work but the third has the advantage that input validations can be implemented, like bean validation and more.
create a class:
public class JsonWrapper {
JsonObject o;
public JsonWrapper(String s) {
this(new JsonParser().parse(s).getAsJsonObject());
}
public JsonWrapper(JsonObject o) {
this.o = o;
}
public String getJsonText() {
return o.getAsString();
}
public DataWrapper get(String field) {
return new DataWrapper(field);
}
public class DataWrapper {
String field;
public DataWrapper() {
}
public DataWrapper(String field) {
this.field = field;
}
public String getData() {
return o.get(field).getAsString();
}
public void setData(String s) {
o.add(field, new JsonPrimitive(s));
}
}
}
convert your live stream to object like this:
List<JsonWrapper> jwList = s.stream().map(s1 -> new JsonWrapper(s1)).collect(Collectors.toList());
setter & getter
Use it in xhtml
<c:forEach items="#{liveStreamController.liveStream.jwList}" var="jw">
<h:outputFormat value="#{jw.get('name').data}" />
<p:inputText value="#{jw.get('order').data}" />
</c:forEach>
Use modified data with:
List<String> jsonList = jw.stream().map(JsonWrapper::getJsonText).collect(Collectors.toList());
I actually have multiple questions regarding Gson.
The first one being if Gson would set the value of a field to null when the provided JSON does not contain any field matching it.
For example, when the provided JSON features the field name but the class I deserialize it to contains name and avatar, would avatar be null?
The next question is in relation to the above one. When I would set a field with an already predefined value, would Gson override it, even if it isn't provided in the JSON (overrides it to null) or would it simply ignore the field and move on?
And finally would I want to know if Gson would still set a value to name when I would use #SerializedName("username") but the JSON contains name.
I want to update my API, including some bad namings of JSON fields, but I want to make the transition of it for the people using it a smooth as possible, so I want to still (temporary) provide the old field name, while also providing support for the new one. Is that possible using the #SerializedName annotation?
I'm still a beginner with Gson and the Gson User Guide wasn't that helpful for me to answer those two specific questions (Or I overlooked it which would also be possible).
I tried implementing this. Here is my code. I hope the output at the end answers your question.
JSON used:
{
"name": "Robert",
"weather": "19 deg"
}
Main class:
public class GSONExample2 {
private static final String jsonStr = "JSON Mentioned above";
public static void main(String[] args) {
GsonDataExample root = new Gson().fromJson(jsonStr, GsonDataExample.class);
System.out.println(root);
}
}
POJO:
class GsonDataExample {
#SerializedName("username")
private String name;
private String avatar;
#SerializedName(value="weather", alternate = "temperature")
private String weather;
private String nameWithDefault = "Default name";
// getters, setters and toString() implemented
}
Output:
GsonDataExample(name=null, avatar=null, weather=19 deg, nameWithDefault=Default name)
To map multiple keys to same attributes, you can use #SerializedName(value="weather", alternate = "temperature") as shown above.
class A{}
class B{}
class C{
private Map<A,B> myMap;
}
class Test{
public static void main(String [] args)
{
Map classMap=new HashMap();
classMap.put("myMap","?");
C c = (C) JSONObject.toBean(jsonObject, C.class,classMap);
}
}
I am using "net.sf.json" library for converting json object into java object.Here in class C there is a map, so how to convert it into Java Object. Here jsonObject is a json representation of class C.
My question is how to convert a json object into Java Object if java Object containing Map
I am a beginner, any help will be very thankful.
I have used jackson library and in that when a json is passed to the java code and if you want to parse that json into a java object you need to have a class which contains all the property which are present in the json string.
for example:
jsonString=
{
'firstname':'json',
'lastname':'jack'
}
will be equivalent to a java class which contains both the property as
class A {
String firstname;
String lastname;
}
so if you accept the string from frontend as the object of class A it works
like
public void (A objectofA){
}
and you call this method from front end and pass a json string using json library it will work and have faith in your work.
I don't know how to do it in "net.sf.json"
Try to see how serialization works in "net.sf.json". Probably, you can go from there.
This is how it is done using jackson, (one of the commenters has tried to explain you an approach using this)
//you need to import:
//import org.codehaus.jackson.map.ObjectMapper;
ObjectMapper mapper = new ObjectMapper();
mapper.writeValueAsString(c) //--> This gives Json String
I don't think this can work, as JSON cannot represent arbitrary objects as keys in maps. In JSON keys have to be strings. So in your example Map would only work if A was String.
Then you could say:
classMap.put("myMap",B.class);
I have a model object which is initialized with default values. To refresh the content of object I call an web service and get the response and get the content from json object.
I want to check If json response contains the object or not. If it does then call the setter and set the data and if it doesn't then leave then don't set it. I have approx 300 fields in my object. How I can do it with less code. I am listing my current approach.
My Model object is like
public class MyObject {
private String str1 = "Initial Value1";
private String str2 = "Initial Value2";
public void setStr1(String str1)
{
this.str1 = str1;
}
public void setStr2(String str2)
{
this.str2 = str2;
}
public String getStr1(){
return str1;
}
public String getStr2(){
return str2;
}
}
my json response be like
{
"val_one":"New Value1",
"val_two":"New_value2"
}
Now at run time I need to set the value from json response
MyObject myObject = new MyObject();
if(jsonObject.has("val_one"));
myObject.setStr1(jsonObject.get("val_one"));
if(jsonObject.has("val_two"));
myObject.setStr2(jsonObject.get("val_two"));
Now how to do it in a better and efficient
If both sides are using JAVA then why not just use json-io. You can create an object as normal. ie
Animal a = new Aminmal() andimal.setName("bob");
Then use json-io to make it into json -- stream to where ever it needs to be... use json io to change back to object
This can be done using
JsonWriter.objectToJson(Object o);
JsonReader.jsonToJava(String json);
https://code.google.com/p/json-io/
json-io is also extremely light weight and quicker than most if not all other third party json library's that I have used.
That being said if you want to have more control on the output ie.. date conversions etc.. then look at GSON.
https://code.google.com/p/google-gson/
Another option, in addition to the other suggestions is gson. Here the link for gson information.
Essentially the idea with gson being that you define an object to represent the JSON structure that you are receiving. So somewhat like what you have now, you'd just need to change the object attributes to match the names of the JSON fields, ie 'val_one' and 'val_two'.
Then you just need to use gson to create the object from the JSON text, eg:
Gson gson = new GsonBuilder().create();
MyObject json = gson.fromJson(jsonStr, MyObject.class);
Why do you want to take of the object model mapping yourself? If you take spring then you can use the jackson mapper and have it all done for you.
If you don't want to use spring then you still can use jackson2 and let it handle the parsing:
http://wiki.fasterxml.com/JacksonRelease20
I have some difficulties with json deserialization using GSon and I hope somebody can help me.
I want to deserialize the following json snippet:
{
"fieldA": "valueA",
"myCollection": {
"AnotherClass": [
{
"objectAfieldA": "valueB",
"objectAfieldB": "valueC"
},
{
"objectAfieldA": "valueD",
"objectAfieldB": "valueE"
}
]
}
}
the corresponding overall class has following fields:
...
String fieldA;
List<AnotherClass> = new ArrayList<AnotherClass>();
....
Now, my problem is that when I deserialize, using fromJson(jsonSample, resultContainer.class), without the List<T> element, everything is good, but I get a NullPointerException when I include the contained list. I've read about how to deal with collections of generic types and the use of TypeToken, but I can't apply this knowledge when my collection is part of another class…
I really would appreciate any help to solve this.
The solution for deserealizing the unnamed JSON array is quite simple:
List<resultContainer> lres = gson.fromJson(new FileReader("input.json"), new TypeToken<List<resultContainer>>(){}.getType());
When deserializing, you only need to use the TypeToken if the outer-most structure to be deserialized into is a generic collection. This is not the case for the example in the original question. So, use of a TypeToken is unnecessary.
The issue appears to be that the JSON structure does not match the Java structure attempting to be bound to.
The JSON structure defines
an object with two elements
element 1 is a string named "fieldA",
element 2 is an object named "myCollection", which has one element
the one element is an array named "AnotherClass", composed of objects with two elements
element 1 is a string named "objectAfieldA",
element 2 is a string named "objectAfieldB"
So, define a Java data structure to match that, and deserialization will work very simply, without any custom processing necessary. If such a matching Java structure is not provided, then custom deserialization is necessary.
Here is such a working example using the names and types from the original question.
import java.io.FileReader;
import com.google.gson.Gson;
public class Foo
{
public static void main(String[] args) throws Exception
{
Gson gson = new Gson();
resultContainer result = gson.fromJson(new FileReader("input.json"), resultContainer.class);
System.out.println(gson.toJson(result));
}
}
class resultContainer
{
String fieldA;
MyCollectionContainer myCollection;
}
class MyCollectionContainer
{
SomeOtherClass[] AnotherClass;
}
class SomeOtherClass
{
String objectAfieldA;
String objectAfieldB;
}