I am parsing a POJO into json using Google's gson library. These are the objects involved:
// Order.java
public class Order {
// ...
private int id;
private String name;
private Location location;
// ...
}
// Location.java
public class Location {
// ...
private String address;
private float latitude;
private float longitude;
private String postcode
// ...
}
When I run it though gson (making sure the Location member variable is not null) using new Gson().toJson(order) I get this results:
{
"id" : 1,
"name" : "nameValue"
}
but I was expecting to get something like this:
{
"id" : 1,
"name" : "nameValue",
"location" : {
"address" : "some address",
"latitude" : 53.346346,
"longitude" : -3.346363,
"postcode" : "23563"
}
}
Can't figure out why is this happening. Has anybody come across this? What can it be that I may be doing wrong?
I have tried setting a custom Type adapter with no luck.
Thanks for your help.
Ok, I figured out what the issue was. I had a mock object factory that created the mock objects using anonymous constructor in the Location type, like this:
Location location = new Location() {
{
setAddress("some address");
setLatitude(53.346346);
setLongitude(-3.356363);
setPostCode("23563");
}
};
So Gson interpreted it as an anonymous class and as it is said in the documentation:
Fields corresponding to the outer classes in inner classes, anonymous classes, and local classes are ignored and not included in serialization or deserialization
I changed it into the normal way of setting up the GsonBuilder and iworks as expected. However I wonder if it would be possible to use this kind of initiation, since it does work for Collections (ArrayList). It makes my mock factories easier to read. :)
Related
i want to exclude a value from JSON Object when passing as input to an API based on the condition. i.e for some scenario that partcular key:value is not requried ,but for some that key:value is need .
Input JSON is as Below
{
"customerNumber" : "6634374019",
"ea" : "",
"source" : "Test",
"dataCentre" : "US",
"requestId" : "CSP-QA-1574"
}
and Class for above is as follows
public class order
{
#JsonProperty(value="customerNumber")
public String customerNumber;
#JsonProperty(value="ea")
public String ea;
#JsonProperty(value="source")
public String source;
#JsonProperty(value="dataCentre")
public String dataCentre;
#JsonProperty(value="requestId")
public String requestId;
//constructor for assiging data
//getters and setters
}
Can any body please help me in this. i do not want to pass "ea" key:value in JSON input for some scenarios and in some i need to pass. how to achieve this.
thnaks in advance
Use:
#JsonIgnore
And be happy.
Cheers
If I had to do this then I would have gone with a slightly different approach.
JsonObject gsonObject=new JsonObject();
gsonObject.addProperty("ea","value");
like that conditionally addProperty().
Since I don't have enough rep So I am putting it like answer instead of comment
You can use #JsonIgnoreProperties on class level if you want to ignore any values that are not passed. If you want to ignore a single value, you can use #JsonIgnore at member level.
#JsonIgnoreProperties({"Ignore 1", "Ignore 2"})
class Sample {
or
class Sample {
private String xyz;
#JsonIgnore
private String ignorethis;
Is it possible to dynamically create a GraphQL schema ?
We store the data in mongoDB and there is a possibility of new fields getting added. We do not want any code change to happen for this newly added field in the mongoDB document.
Is there any way we can generate the schema dynamically ?
Schema is defined in code, but for java(schema as pojo), when new
attribute is added, you have to update and recompile code, then
archive and deploy the jar again. Any way to generate schema by the
data instead of pre-define it?
Currently we are using java related projects (graphql-java, graphql-java-annotations) for GraphQL development.
You could use graphql-spqr, it allows you auto-generate a schema based on your service classes. In your case, it would look like this:
public class Pojo {
private Long id;
private String name;
// whatever Ext is, any (complex) object would work fine
private List<Ext> exts;
}
public class Ext {
public String something;
public String somethingElse;
}
Presumably, you have a service class containing your business logic:
public class PojoService {
//this could also return List<Pojo> or whatever is applicable
#GraphQLQuery(name = "pojo")
public Pojo getPojo() {...}
}
To expose this service, you'd just do the following:
GraphQLSchema schema = new GraphQLSchemaGenerator()
.withOperationsFromSingleton(new PojoService())
.generate();
You could then fire a query such as:
query test {
pojo {
id
name
exts {
something
somethingElse
} } }
No need for strange wrappers or custom code of any kind, nor sacrificing type safety. Works with generics, dependency injection, or any other jazz you may have in your project.
Full disclosure: I'm the author of graphql-spqr.
After some days' investigation. I found it is hard to generate schema dynamically in Java (or cost is so high).
Well, from another way. I think we can use Map as a compromised way to accomplish that.
POJO/Entity
public class POJO{
#GraphQLField
private Long id;
#GraphQLField
private String name;
// ...
#GraphQLField
private GMap exts;
}
GMap is a customized Map (Because Map/HashMap is a JDK inner class which could not make as GraphQL Schema but only extend).
GMap
public class GMap extends HashMap<String, String> {
#GraphQLField
public String get(#GraphQLName("key") String key) {
return super.get(key);
}
}
Retrieve data from Client
// query script
query test
{
your_method
{
id
name
exts {
get(key: "ext") // Add a extended attribute someday
}
}
}
// result
{
"errors":[],
"data":
{
"list":
[
{"id":1, name: "name1", exts: {"get": "ext1"}},
{"id":2, name: "name2", exts: {"get": "ext2"}}
]
}
}
I am in a process of creating a library for Windows Azure. So, here is a simple generic method to insert a new record:
public <TEntity extends SyncableBase> void addRemoteItem(TEntity itemToAdd) {
MobileServiceTable<TEntity> remoteTable = (MobileServiceTable<TEntity>)mobileServiceClient.getTable(itemToAdd.getClass());
Gson gson = new Gson();
String json = gson.toJson(itemToAdd);
remoteTable.insert(itemToAdd, new TableOperationCallback<TEntity>() {
public void onCompleted(TEntity entity, Exception exception, ServiceFilterResponse response) {
if (exception == null) {
Log.e("SuccessMe", "Success");
// Insert succeeded
}
else {
Log.e("SuccessMe", "Nah "+ exception.getMessage());
// Insert failed
}
}
});
}
Now, here is my SyncableBase class:
public class SyncableBase {
#SerializedName("Bingo")
private int localId;
//#SerializedName("id")
private String remoteId;
private boolean isDeleted;
}
And my ToDoItem class:
public class ToDoItem extends SyncableBase {
private String name;
}
Now, the problem is: This fails with Error processing request. But if I don't extend ToDoItem from SyncableBase and move all those members directly to the former, everything works just fine. As can be seen, I tried serializing my Java object just before calling inset. The serialized json is exactly the same in both the cases. What am I doing wrong?
After days of debugging, I have come up with a potential problem and it's definite solution. This holds valid for the Android Azure SDK valid at the time of writing this. A couple of notes:
For seamless transactions, the id member must be present in the inherited class and not the super class. While validating the object, Azure SDK uses reflection and tries to find a filed with name (or serialized name) equal to id or Id. Somehow, the member isn't found if it is present in super class and we get error.
GSON (the thing which serializes Java object to JSON) is configured inside SDK so that it serializes even the null members. So, when there are no columns in WAMS table (fresh table) and try to insert an item with null fields, the error is thrown. The filed must hold a value so that the type of corresponding column to be generated can be determined. A new field with null value will give you an error.
Here's an example of an item being put in a fresh table.
{
"id": "Awesome unique id",
"name": Beautiful Wallpaper",
"description": null
}
Here, the WAMS would know that it has to generate a column called description; however, it wouldn't know the type of this column. Hence, first object must always have non-null values.
In my particular case, both the problems are there. Taking care of these things solved them.
I was given json file and third party class:Dealer and interface IDealerAttributes (I can not change either of them);
(I remove package name and imports to make the code simple)
JSON file
{
"serviceURL": "com.mycompany.serviceURL",
"dealerAttributes": [
{
"language": "language0",
"dealerAttributeName": "dealerAttributeName0",
"updateDate": 0
},
{
"language": "language1",
"dealerAttributeName": "dealerAttributeName1",
"updateDate": 1
}
]
}
class Dealer {
private String serviceURL;
private List dealerAttributes;
public Dealer() {
dealerAttributes = new ArrayList();
}
//Getters and Setters...
}
public interface IDealerAttributes {
public String getLanguage();
public String getDealerAttributeName();
public long getUpdateDate();
}
once I use:
gson.fromJson(jsonObj.toString(), Dealer.class);
I will get exception from this line:
Exception unmarshalling json String into Object: com.google.gson.JsonParseException: The JsonDeserializer com.google.gson.DefaultTypeAdapters$CollectionTypeAdapter#60e26ffd failed to deserialize json object [{"language":"language0","dealerAttributeName":"dealerAttributeName0","updateDate":0},{"language":"language1","dealerAttributeName":"dealerAttributeName1","updateDate":1}] given the type java.util.List
How can I read this json file based on Dealer.class, IDealerAttributes?
But I can add one class, let's say:
public class DealerAttributes implements IDealerAttributes {
private String language;
private String dealerAttributeName;
private long updateDate;
public DealerAttributes() {
}
//Getters and Setters...
}
Since I am new to json/gson, would you please give detailed instruction to help me out? Thanks.
[added]
Consider if there are 100 fields in Dealer class, and there are another 100 interface used/nested in Dealer. I am thinking whether anyone have experience using this way: (MyType is interface)
gson.registerTypeAdapter(MyType.class, new MyType());`
You could map it to a List of Maps and then use a BeanMapper like http://code.google.com/p/orika/ to get some more informative error messages
I'm trying to parse a JSON feed using Gson in Android. I know the JSON is valid. I suspect that it is because the format is like this:
"Info":[
{
"Id":"",
"Name":"",
"Description":"",
"Date":""
}
In order to parse this I need to "dot" in. Ex: Info.Name
How can I do this in a serialized DTO?
#SerializedName("Name")
public String name;
#SerializedName("Description")
public String desc;
#SerializedName("Date")
public String date;
I tried to put "Info." in front of each serializedName but that didn't work either. I also know my JSON parsing method works properly, because it's used somewhere else with a different DTO. But in that parsing, I don't have to "dotting" issue.
Can anyone help?
EDIT: I have tried everything you guys posted, and nothing works. The error says:
The JsonDeserializer failed to deserialize json object {"Info":[{".......
SECOND EDIT:
I was able to get rid of the error, but now it returns null. Haha, getting pretty damn frustrated right about now!
I am assuming that the actual JSON you are intaking is valid because the example you provided is not. In your JSON example, you have "Info":[ but there is no outer object containing the "Info" property, which is a must. The valid JSON would be:
{
"Info": [
{
"Id":"",
"Name":"",
"Description":"",
"Date":"",
}
]
}
This is a JSON object that has a property "Info" which has a value that is a list of objects. This list of objects contains one object that has the properties "Id", "Name", "Description", and "Date", all of which have empty-string values.
Here is a quick tutorial on how to use GSON to parse a JSON feed such as the above JSON:
You will need a class to represent the items in the list:
public class InfoItem {
public String Id;
public String Name;
public String Description;
public String Date;
public InfoItem() {}
}
And one to represent the list of Items:
public class InfoItemList extends LinkedList<InfoItem> {
public InfoItemList() { super() };
}
This added complexity is because GSON cannot otherwise get the type of a generic collection from the class data.
And one to represent the overall JSON message:
public class InfoMessage {
public InfoItemList Info;
public InfoMessage() {};
}
And then just:
gson.fromJson(jsonString, InfoMessage.getClass());
If just de-serializing a collection:
Type listType = new TypeToken<List<InfoItem>>() {}.getType();
gson.fromJson(jsonString2, listType);
The Info object is a list because of the []. You have to use the following code to deserialze it:
EDIT:
public class Info {
// as in your question
public String name;
...
}
public class Data {
#SerializedName("Info")
public List<Info> info;
}
Then just use the data class to deserialize your json.