I have a List of javascript objects on my client side, which are a list of "events" that a user has executed. When the user is ready, I want to send this to the server. The order of events is important, so preserving the list order is necessary.
What I would like to do is to have a JSON library (don't mind which one) to bind the JSON to some Event objects in my Java code, where Event is an abstract class, and I have 3 concrete classes that all extend Event (lets say EventA, EventB and EventC).
Ideal scenario would be something like
List<Event> events = jsonlibrary.deserialise(jsonString);
which may contain a list of items such as
[eventA, eventC, eventA, eventA, eventB]
Is this possible, or do I have to inspect the JSON tree manually, and deserialise the individual elements of the json array?
JSON objects are just key/value pairs and contain no type information. That means identifying the type of a JSON object automatically isn't possible. You have to implement some logic on the server-side to find out what kind of event you are dealing with.
I would suggest to use a factory method which takes a json string, parses it to find out what kind of Event it is, builds an Event object of the correct subclass and returns it.
You could use Genson library http://code.google.com/p/genson/.
It can deserialize to concrete types if the json was produced using Genson. Otherwise you only need to add something like [{"#class":"my.java.class", "the rest of the properties"}...]
// an example
abstract class Event {
String id;
}
class Click extends Event {
double x, y;
}
// you can define aliases instead of plain class name with package (its a bit nicer and more secure)
Genson genson = new Genson.Builder().setWithClassMetadata(true).addAlias("click",
Click.class).create();
String json = "[{\"#class\":\"click\", \"id\":\"here\", \"x\":1,\"y\":2}]";
// deserialize to an unknown type with a cast warning
List<Event> events = genson.deserialize(json, List.class);
// or better define to which generic type
GenericType<List<Event>> eventListType = new GenericType<List<Event>>() {};
events = genson.deserialize(json, eventListType);
EDIT
here is the wiki example http://code.google.com/p/genson/wiki/GettingStarted#Interface/Abstract_classes_support
Why not using jackson json library ?
It is a full Object/JSON Mapper with data binding functionnality.
It is fast, small footprint, documented, overused, and many others things you will enjoy!
I began a library that implements the desired fonctionality (for json and xml) if the json is encoded by the same library :
https://github.com/giraudsa/serialisation
to use it,
MyObject myObject = new SpecialisedObject();
String json = JsonMarshaller.ToJson(myObject);
MyObject myClonedObject = JsonUnMarshaller(json);
Related
I have List<Person> where its JSON output is like:
[{"name":"john","email":"john#email.com"},
{"name":"daniel","email":"daniel#email.com"},
{"name":"thomas","email":"thomas#email.com"}]
and a count of the persons where its JSON format is like: {"number":3}
How can I combine the above two to get the result:
{
"number":3,
"persons":[{"name":"john","email":"john#email.com"},
{"name":"daniel","email":"daniel#email.com"},
{"name":"thomas","email":"thomas#email.com"}]
}
my Java code is jersey2 based JAX-RS application. to make more clear, I have a list of Person fetched from database and i also have an integer variable number. and combine the List and the integer variable to get above result in an efficient and robust way.
Since you are using a framework that already does conversion to JSON automatically, the easiest way would be to just return a new object.
public class Result {
private int number;
private List<Person> persons;
//leaving creation of constructor to you
}
And then just instantiate that object and return it.
When you want to map Object to json directly or want to convert json to object, you can use GSON library . this will give you more flexibility and control.
Download link - http://code.google.com/p/google-gson/
Tutorial link - http://www.mkyong.com/java/how-do-convert-java-object-to-from-json-format-gson-api/
I am using Spring and Java and implementing REST Based services. I have a set of developers who develop for mobile,iPad and Web too. Consider I have a bean
Class User{
private String Name;
private Integer id;
private String photoURL;
private ArrayList<String> ProjectName;
private ArrayList<String> TechnologyList;
private ArrayList<String> InterestList;
//Getters and setters
}
While the Web Developers need the entire fields and mobile developers just require two fields from it whereas the iPad requires something in between mobile and web.
Since I am using jackson as a parser, is there a way where while requesting to the controller I can specify which all data I require and avoid the others. For example consider I do a GET request like
GET>http://somedomain.com/users?filter=name,id,photoUrl
Which returns me a JSON structure something like
{
"name":"My Name",
"id":32434,
"photoUrl":"/sss/photo.jpg"
}
Sameway if someone asks for some more fields, they could be filtered. Please let me know how this can be done so that my API remains generic and useable for all.
You can achieve what you want but some extra work is necessary. I can offer you two solutions.
1. Return a Map
Simply put every property that is requested into the map.
2. Use Jacksons Object Mapper directly
Jackson lets you set filters that specify which properties are serialized or ignored.
FilterProvider filter = new SimpleFilterProvider().addFilter("myFilter",
SimpleBeanPropertyFilter.filterOutAllExcept(requestedProperties));
String json = objectMapper.writer(filter).writeValueAsString(value);
You can then return the JSON string directly instead of an object.
For both solutions you would ideally write a class that does the job. But if you do that you could as well write your own message converter. You could extend the MappingJackson2HttpMessageConverter, for instance, and overwrite the writeInternal method to suit your needs. That has the big advantage that you don't need to change your controllers.
The straightforward solution is to implement custom Jackson JSON serializer that will get field names that should be serialized from thread local storage and then serialize only fields which names are presented in that context. For other hand, in controller you can grab all allowed fields names from url and store them into thread local context. Hope this helps.
I' m developing a RESTful Android mobile client. Information exchange between my app and server is in JSON. So I' m now a little bit confused what data structure choose for represent JSON responses and data because there a lot of them. I've just stopped with LinkedHashMap<> but as far as i know JSON is unordered. Across the Internet I saw people use Map<> or HashMap<> for this. So the question - what is the best data structure for this purpose? Or if there is no a univocal answer - pros and cons of using data structures I' ve mentioned.
I would disagree with the first answer. The REST paradigm was developed so that you would operate with objects, rather than operations.
For me the most sensible approach will be if you declare beans on the client side and parse the json responses and request through them. I would recommend using the GSON library for the serialization/ deserialization. JsonObject/ JsonArray is almost never the best choice.
Maybe if you give examples of the operations you are about to use we might be able to help more precisely.
EDIT: Let me also give a few GSON Examples. Let's use this thread to compare the different libraries.
In the most cases REST services communicate objects. Let's assume you make a post of product, which has reference to shop.
{ "name": "Bread",
"price": 0.78,
"produced": "08-12-2012 14:34",
"shop": {
"name": "neighbourhood bakery"
}
}
Then if you declare the following beans:
public class Product {
private String name;
private double price;
private Date produced;
private Shop shop;
// Optional Getters and setters. GSON uses reflection, it doesn't need them
// However, better declare them so that you can access the fields
}
public class Shop {
private String name;
// Optional Getters and setters. GSON uses reflection, it doesn't need them
// However, better declare them so that you can access the fields
}
You can deserialize the json using:
String jsonString; // initialized as you can
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setDateFormat("MM-dd-yyyy HH:mm"); // setting custom date format
Gson gson = gsonBuilder.create();
Product product = gson.fromJson(jsonString, Product.class);
// Do whatever you want with the object it has its fields loaded from the json
On the other hand you can serialize to json even more easily:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setDateFormat("MM-dd-yyyy HH:mm"); // setting custom date format
Gson gson = gsonBuilder.create();
String jsonString = gson.toJson(product);
Are you talking about receiving and parsing the JSON string from a server request?
For that you can use:
import org.json.JSONArray;
import org.json.JSONObject;
Using these, I read through my JSON array from my POST request and store the resulting information in Class objects in my project.
For each item in JSONArray, you can extract the JSONObject and attributes like this:
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
jsonObject.getString("text");
}
As far as actually storing the data, like mentioned above, JSON data can come in a wide array of formats depending on the source, and as such, it is usually parsed on the client end and saved in your application Class objects for use. Or more generically, you could store the data using Map<String, Object>
This is easily the best answer I've seen:
https://dzone.com/articles/which-is-the-right-java-abstraction-for-json
Summary: there are three abstrations: pojos, maps and lists, and custom classes to represent objects, arrays, and primitives. There are advantages and disadvantages to each, with no clear winner.
Pojos have the biggest advantages, but you can't always use them. Use them if you can, and use the others if you must.
If you are doing anything other than the most simple mapping then you should use a full class structure. Create your class hierarchy as a mirror of the data structure in JSON and use Jackson to map the JSON directly to the class hierarchy using the ObjectMapper.
With this solution you don't have any casting of Object to Map or messing around with JSONObject or JSONArray and you don't have any multi-level map traversal in your code. You simply take the JSON string, feed it to the ObjectMapper, and get a your Object, which contains child objects (even collections) automatically mapped by the ObjectMapper.
I've used xstream to serialize JSON, in the following way:
XStream xstream = new XStream(new JsonHierarchicalStreamDriver());
xstream.setMode(XStream.NO_REFERENCES);
xstream.alias("myAlias", MyClass.class); // requires a no argument constructor
System.out.println(xstream.toXML(product));
Ok, the gentleman in the comments wants a deserialization example, here you are:
XStream xstream = new XStream(new JsonHierarchicalStreamDriver());
xstream.alias("myAlias", MyClass.class);
Product product = (Product)xstream.fromXML(json);
System.out.println(product.getName());
Let me know if you need further assistance...
I am writing a RESTful web service using Java and Jersey, where the service will accept either XML or JSON inputs. Jackson is used as the JSON deserializer, and integrated into the Jersey config.
One of the endpoints is a POST request to a URL, where the content can be one of several different Java classes, and there is a common base class. These classes - with XML annotations - are:
#XmlRootElement(name = "action")
#XmlAccessorType(XmlAccessType.NONE)
#XmlSeeAlso({ FirstAction.class, SecondAction.class, ThirdAction.class })
public abstract class BaseAction {
}
#XmlRootElement(name = "first-action")
#XmlAccessorType(XmlAccessType.NONE)
public class FirstAction extends BaseAction implements Serializable {
}
// Likewise for SecondAction, ThirdAction
In my resource I can declare a method like:
#POST
#Path("/{id}/action")
public Response invokeAction(#PathParam("id") String id, BaseAction action) {...}
Then I can POST an XML fragment that looks like <firstAction/> and my method will be invoked with a FirstAction instance. So far so good.
Where I'm struggling is getting the JSON deserialization to work as seamlessly as the XML deserialization. Where the #XmlSeeAlso annotation was critical to get the XML deserialization working properly, it seemed that the equivalent for JSON was #JsonSubTypes. So I annotated the classes like this:
// XML annotations removed for brevity, but they are present as in the previous code snippet
#JsonSubTypes({ #JsonSubTypes.Type(name = "first-action", value = FirstAction.class),
#JsonSubTypes.Type(name = "second-action", value = SecondAction.class),
#JsonSubTypes.Type(name = "third-action", value = ThirdAction.class) })
public abstract class BaseAction {
}
#JsonRootName("first-action")
public class FirstAction extends BaseAction implements Serializable {
}
// Likewise for SecondAction, ThirdAction
I then feed it my test input: { "first-action": null } but all I can get is:
"org.codehaus.jackson.map.JsonMappingException: Root name 'first-action' does not match expected ('action') for type [simple type, class com.alu.openstack.domain.compute.server.actions.BaseAction]"
Unfortunately since I'm trying to be compatible with someone else's API I can't change my sample input - { "first-action": null } has to work, and deliver to my method an object of class FirstAction. (The action doesn't have any fields, which is why null shouldn't be a problem - it's the type of the class that's important).
What's the correct way to have the JSON deserialization work in the same way as the XML deserialization already is?
If you are using Jackson, you are looking for #JsonTypeInfo and #Type . Please see here for more information
JSON does not work the way XML does, so the solution is not identical.
What you need to use is (like the other answer said), #JsonTypeInfo. That only triggers inclusion and use of the type identifier. If so, then '#JsonSubTypes` will be of use in deserialization.
The reason this indicator must be used is simple: if you have more than one alternative type to deserialize to, there must be something to differentiate.
Note, too, that this does NOT have to be a property -- while most users choose "As.PROPERTY" inclusion, it is not (IMO) the best way. "WRAPPER_OBJECT" may be what you are looking for, as it adds an extra intermediate JSON property, which is somewhat similar to what XML does.
I investigated the use of #JsonTypeInfo but ran into problems because I could not alter the input format. The parser absolutely had to be able to handle input { "first-action":null }. This ruled out the possibility of adding an #type or #class property. Using a wrapper object may have worked, but it choked on the null payload.
A crucial point was that I was using the UNWRAP_ROOT_PROPERTY configuration option. Jackson was absolutely insisting on finding an action property and I could not get it to consider anything else. So, I had to selectively disable UNWRAP_ROOT_PROPERTY for certain domain objects, so that Jackson would be open to parsing alternatives. I modified the project's ContextResolver.getContext(...) implementation to check for a #JsonRootName annotation - since this only has meaning if wrapping is enabled, I used the presence of this annotation to determine whether to return an object mapper configured with root property wrapping on, or off.
At this stage, I might have been able to use #JsonTypeInfo(include=JsonTypeInfo.As.WRAPPER_OBJECT, ...), except for the issue with the null payload mentioned above (this is used to indicate that the child object has no properties - if the spec I was working from had given an empty object {} instead then there would not be a problem). So to proceed I needed a custom type resolver.
I created a new class that extended org.codehaus.jackson.map.TypeDeserializer, with the purpose that whenever Jackson is called to deserialize a BaseAction instance, it will call this custom deserializer. The deserializer will be given a subtypes array, which for BaseAction maps first-action, second-action, etc. to FirstAction.class, etc. The deserializer reads the input stream for the field name, then matches the name to a class. If the next token is an object, then it finds and delegates to the appropriate deserializer for that class, or if it is null it finds the no-args constructor and invokes it to get an object.
A class that implements org.codehaus.jackson.map.jsontype.TypeResolverBuilder is needed that can build an instance of this previous class, and then the TypeResolverBuilder is given as a #JsonTypeResolver annotation on the BaseAction class.
I have an application which makes use of an external library (Jackson), and the method I need requires a class literal as an argument. So if I wish to parse my JSON string into a User object:
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(new File("user.json"), User.class);
Now, I wish to use this method dynamically (i.e. parse different JSON strings using the same line of code). For example:
String json1 = "{"type":"jacket",...}";
String json2 = "{"type":"sweater",...}";
Object object = mapper.readValue(json1/json2, ???);
//returns a Jacket object OR Sweater object based on the "type" key
//i.e. use Jacket.class as the 2nd argument if "type" is "jacket"
//OR Sweater.class if "type" is "sweater"
//After getting the deserialized object,
//if object is Jacket, cast as a Jacket
//if object is Sweater, cast as a Sweater
Of course, the JSON string in question can be for any class, so I can't simply hard-code an if-else loop. I've looked at custom serializers, but frankly am quite lost at what it's talking about, and would like some help in how I can go about this.
In summary, I need some way to first define a class literal from a String, and then cast the resulting Object into the specific class (but my focus is on getting readValue to work dynamically).
Looks like you need a mapping somewhere between JSON type variable and Java class type.
Generally result should be something like this map:
Map<String, Class<? extends YourSupertype>> map = new HashMap<>();
map.put("sweater", Sweater.class);
map.put("jacket", Jacket.class);
Just store possible clothing types somewhere in a file, then do something like:
String clothingType = nextEntryFromFile();
String className = constructClassNameFromClothingType(clothingType);
map.put(clothingType, Class.forName(className));
Since version 1.5 Jackson supports Polymorphic Type Handling, check here http://www.cowtowncoder.com/blog/archives/2010/03/entry_372.html
there are examples on how to correctly handle deserialization in those cases.