Here is my function which is adding two different objects.
#GET
#Path("/getApplicationEnv")
#Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public List<Object> getApplicationEnv(){
List<ApplicationDTO> allApplication = applicationService.getAllApplication();
List<Application> Applist = new ArrayList<Application>();
for(ApplicationDTO d: allApplication)
{
Application a = new Application();
a.setApplicationId(d.getApplicationId());
a.setApplicationName(d.getApplicationName());
a.setCreateTime(d.getCreateTime());
a.setOwner(d.getOwner());
Applist.add(a);
}
List<EnvironmentDTO> allEnvironments = environmentService.getAllEnvironments();
List<Environment> Envlist = new ArrayList<Environment>();
for(EnvironmentDTO d: allEnvironments)
{
Environment e = new Environment();
e.setEnvironmentId(d.getEnvironmentId());
e.setEnvironmentName(d.getEnvironmentName());
e.setOwner(d.getOwner());
e.setCreateTime(d.getCreateTime());
Envlist.add(e);
}
ArrayList<Object> obj= new ArrayList<Object>();
obj.addAll(Applist);
obj.addAll(Envlist);
return obj;
}
Currently I am using ArrayList of Object for adding two objects, but I am getting following error:
*SEVERE: A message body writer for Java class java.util.ArrayList, and Java type java.util.List, and MIME media type application/xml was not found
*
I have tried making a common parent class but I am having some attributes of both the class common so it is not possible to have a common parent class.
Can anyone please suggest me a way to achieve this ?
you can try changing
ArrayList<Object> obj= new ArrayList<Object>();
obj.addAll(Applist);
obj.addAll(Envlist);
to
ArrayList<MyModel> obj= new ArrayList<MyModel>();
MyModel mm = new MyModel();
mm.setVal1(Applist);
mm.setVal2(Envlist);
obj.add(mm);
UPDATE
class MyModel
{
private ApplicationDTO appDTO;
private EnvironmentDTO enDTO;
//getters settters here
}
here MyModel is just a model class with two fields as per your requirement..
hope this helps
The problem is that object is not considered as an xml element. You can create an object like this
#XmlRootElement
public class MyObject{
private List<Application> somename;
private List<Environment> somename2;
//Getters
//setters
}
and do like this
public List<MyObject> getApplicationEnv(){
/*Some code*/
}
Related
I have multiple types of objects, I'd like to generalise the 'id' of the objects in a way that will dynamically change what field is selected as the id.
Example
public class ObjectA{
//Attribute name attA
private String attA;
.... More attributes
public String getAttA(){
return attA
}
.....More getters/setters
}
public class ObjectB{
//Attribute named attB
private String attB;
.... More attributes
public String getAttB(){
return attB
}
.... More getters and setters
}
Id like to be able to run something like this:
Map<????, ????> customIdMap = new HashMap<>();
//We decide that ObjectA main attribute is AttA
customIdMap.add(ObjectA.class, ObjectA::getAttA);
//We decide that ObjectB main attribute is AttB
customIdMap.add(ObjectB.class, ObjectB::getAttB);
Then I'll be able to have a list of general objects and ill be able to retrieve their ids from the map if it is a known object with:
public String getCustomId(Object object){
if(customIdMap.contains(object.getClass()){
//Parameters are messed up, but this is the general idea of how
//i thought this would look
return customIdMap.get(object.getClass()).apply(object);
}
}
The code above does not run since getAttA is a call to a none static method in a static context so i assume this maybe should be wrapped in some kind of generic object.
Can it be done?
Preferably you change ObjectA and ObjectB to have a common interface. If that's not possible you can put them into a map like this:
Map<Class<? extends Object>, Function<Object, String>> map = new HashMap<>();
map.put(ObjectA.class, a -> ((ObjectA) a).getAttA());
map.put(ObjectB.class, b -> ((ObjectB) b).getAttB());
EDIT:
Or if you would like to encapsulate it into a typesafe heterogeneous container:
public static class ToIdMap {
private final Map<Class<?>, Function<Object, String>> map = new HashMap<>();
public <X> void put(Class<X> clazz, Function<X, String> func) {
map.put(clazz, (Function<Object, String>) func);
}
public String toIdString(Object o) {
return map.get(o.getClass()).apply(o);
}
}
EDIT2: Note that neither of these solutions work for subclasses, but it could be supported by traversing the class hierarchy in toIdString.
Your wording is a bit unclear, but I assume you want to get the ID of an object, even when they are different classes. This is the problem that interfaces solve.
You can create an interface, with one method called getId(), which will return the id. Then, you can just call getId() on any type of object with an id.
For example:
public interface Identifiable {
String getId();
}
public class ObjectA implements Identifiable {
// same for ObjectB
#Override
public String getId() {
return id;
}
}
Then, in your code:
Identifiable i1 = new ObjectA();
Identifiable i2 = new ObjectB();
System.out.println(i1.getId());
System.out.println(i2.getId());
EDIT:
It still looks like an interface is the cleanest way of solving your problem. For completeness, the following will work:
Map<Class, Function<?, String> map = new HashMap<>();
map.put(Object1.class, (Object1 o) -> o.getAttrA); // repeat for ObjectB
It can then be called with:
if (obj instanceof Object1) return map.get(Object1.class).apply((ObjectA) obj);
Ended up doing this weird solution:
class Mapping<T> {
private Function<T, String> idFunc;
public Mapping(Function<T, String> idFunc) {
this.idFunc = idFunc;
}
public String apply(T obj) {
return idFunc.apply(obj);
}
}
}
private Map<Class, Mapping> mappings = new HashMap<>();
mappings.put(ObjectA.class, new Mapping<>(ObjectA::getAttA);
mappings.put(ObjectB.class, new Mapping<>(ObjectB::getAttB);
public String getObjectID(Object object){
String id = null;
if(mappings.containsKey(object.getClass())){
id = mappings.get(object.getClass()).apply(object);
}
return id;
}
I speak Spanish, use the translator to ask this question, Sorry for the spelling.
Also, do not be like asking exactly what I want to do.
I want to create a list of an object passing through parameter.
public void createListUnknown(? Class myClass? or ? Object myObject?) {
List<myClass> my_list;
//or
List<myObject> my_list;
}
example use:
public class Model{
public String name;
public String age;
}
as it should be?
createListUnknown(?? MyModel ??)
Basically I want to create a list with an object that comes parameter to a function
An example where you want to apply is the following:
//final GsonModelUsuariosLoginGet gsonModelUsuariosLoginGet
//= gson.fromJson(responseData, GsonModelUsuariosLoginGet.class);
return gson.fromJson(responseData, httpObject.getObjectGet().getClass());
and
Object aClass = httpObject.getObjectGet().getClass();
List< httpObject.getObjectGetClass() > aClasses;
Type collectionType = new TypeToken<List<aClass>>(){}.getType();
final List<GsonModelArticulos> articulos = gson.fromJson(responseData, collectionType);
create list
public <T> List<T> makeList(Class<T> type) {
return new ArrayList<T>();
}
get type list
Using the Type interface.
private <T> Type getType(Class<T> type) {
Type typeOfObjectsListNew = new TypeToken<ArrayList<T>>() {}.getType();
return typeOfObjectsListNew;
}
I'm new to marshalling and unmarshalling. I want to marshal and unmarshal a generic List using DynamoDBMashaller
I have following class with me
public class ListObjectConverter implements DynamoDBMarshaller<List<?>>
{
private static final Gson GSON = new Gson();
#Override
public String marshall(List<?> value) {
Type listOfObjectType = new TypeToken<List<?>>(){}.getType();
return GSON.toJson(value, listOfObjectType);
}
#Override
public List<?> unmarshall(Class<List<?>> clazz, String value) {
Type listOfObjectType = new TypeToken<List<?>>(){}.getType();
return GSON.fromJson(value, listOfObjectType);
}
}
Marshalling is working fine
List<Source> fsl = new ArrayList<>();
//add few element in fsl
ListObjectConverter loc = new ListObjectConverter();
String marshalled = loc.marshall(fsl);
This works perfectly.
But I'm a little confused how do I call unmarshaller in this case. Following code is not compiling. It says Found java.lang.Class<java.util.List> : required java.lang.Class<java.util.List<?>>
List<Source> fsl1 = loc.unmarshall(List.class , marshalled);
I think type eraser is coming in picture.
Is it possible to do it? If yes, how do I do that? Any alternative you could suggest?
Thanks in advance
You need cast
List<FeedSource> lst= new ArrayList<FeedSource>();
lst= loc.unmarshall((Class<List<FeedSource>>) lst.getClass(), marshalled);
Here is example of JSON response str:
{"myServiceMethodResult":[{"BoolPropertyOfFooClass":false,"StringPropertyOfFooClass":"tstString", "Bar":[{"BoolPropertyOfBarClass":false,"StringProperyOfBarClass":"tst"}]
}]
}
Service is returning List
List<Foo> myServiceMethod(){
return new List<Foo> myFooList
}
This are the classes:
#JsonRootName(value = "myServiceMethodResult")
Class Foo{
public boolean BoolPropertyOfFooClass
public String StringPropertyOfFooClass
#JsonProperty(value = "Bar")
public List<Bar> myBar;
public boolean getBoolPropertyOfFooClass(){
return BoolPropertyOfFooClass;
}
public void setBoolPropertyOfFooClass(bool value){
this.BoolPropertyOfFooClass = value
}
public String getStringPropertyOfFooClass(){
return StringPropertyOfFooClass;
}
public void setBoolPropertyOfFooClass(String value){
this.StringPropertyOfFooClass = value
}
public List<Bar> myBar() {
return myBar;
}
public void setmyBar(List<Bar> value) {
this.myBar= value;
}
}
I'm usign Jackson parser and first of all Parsing JSON string to an object is surprising slow (despite a fact that this file is huge (2 MB)
String jsonStr = sh.makeServiceCall(serviceUrl/MethodName, ServiceHandler.POST, json_content_parameters);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
JsonNode node = null;
myFooInstance= mapper.readValue(new StringReader(jsonStr), new TypeReference<List<Foo>>(){});
mapper.readValue is hitting exception myServiceResult does not match expected ('List'). Further more, if I'm using readTree function it takes 5 seconds (but not hittign exception). Is there any better way of getting Object faster,
Further more I'm not able to figure how to map List of Bar objects inside my Foo objects. I'm able to set my properties using this line of code:
TypeReference<List<Foo>> typeRef = new TypeReference<List<Foo>>(){};
myInstanceFoo= mapper.readValue(node.traverse(), typeRef);
So I Have my List of Foo objects but I'm not able to get List inside of list using something simmilar. Any help about problems with duration, or setting inner List object would be appreciated
Trace:
com.fasterxml.jackson.databind.JsonMappingException: Root name 'MyMethodResponse' does not match expected ('List') for type [collection type; class java.util.List, contains [simple type, class com.package.Foo]]
at [Source: java.io.StringReader#411dc790; line: 1, column: 2]
Since it appears that you have the response wrapped in a single-member object instance, you have the option of annotating your Foo class with this:
#JsonRootName("MyMethodResponse")
IMPORTANT: the name is FIXED.
However you are not done yet. You need to configure your ObjectMapper to use this annotation:
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE);
Your have another problem. Namely, your List<Bar> has name myBar in your POJO, but Bar in the produced JSON. You need to annotate your myBar field with #JsonProperty:
#JsonProperty("Bar")
In case Someone stumbles on a same problem I figured it out. To serialize Foo class if JSON is in format
{"response":[{"propertyOfFooClass":"something"
}]
}
you nedd to Create Root Class that contains list of Foo Class
public class RootWrapper {
private List<Foo> foo;
public List<Foo> getFoos() {
return channels;
}
#JsonProperty("response")
public void setFoos(List<Foo> fooList) {
this.foo= fooList;
}
RootWrapper mj = mapper.readValue(jsonStr, RootWrapper.class);
Cheers
I need an advice. I'm trying to pass a list of objects as parameters to a method controller written with spring-mvc 3, all this with ajax. These objects are decendants of a widget class. i will show you the code first
the ajax call:
function buildWidget(obj){
var result = null;
switch(obj.className){
case 'text':
result = {
x:obj.control.x
,y:obj.control.y
,height: obj.control.height
,width: obj.control.width
,text: obj.text
};
break;
case 'youtube':
result = {
x:obj.control.x
,y:obj.control.y
,height: obj.control.height
,width: obj.control.width
,videos: obj.videos
};
break;
}
return result;
}
var all = new Array();
for(i=0;i<figures.size;i++)
all.push(buildWidget(figures.data[i].widget));
jQuery.getJSON("pages/save.html", { widgetsList: jQuery.toJSON(all) }, function(myresult) {
alert('ok');
});
the server side
the classes
public class WidgetAdapter {
private int x;
private int y;
private int width;
private int height;
// getters and setters
}
public class TextWidgetAdapter extends WidgetAdapter {
private String text;
// getters and setters
}
public class YoutubeWidget extends WidgetAdapter{
private String videos;
// getters and setter
}
the controller (the problem here)
#RequestMapping(value = "/pages/save",method=RequestMethod.GET)
public #ResponseBody String save(#RequestParam String widgetsList){
Type listType = new TypeToken<List<WidgetAdapter>>() {}.getType();
List<WidgetAdapter> adapters = new Gson().fromJson( widgetsList, listType);
for(WidgetAdapter a :adapters){
System.out.println(a.getX());
}
return new Gson().toJson(new ActionResult("msg"));
}
so, when the method controller is called Gson creates a List adapters, all elements are of class WidgetAdapter and not TextWidgetAdapter or YoutubeWidget. Is there a way to acheive that?? i mean pass parameters as list of element decendants of a class and be transformed correctly by Gson?
Thanks, i hope be clear. english is not my native language.
pd: i´m doing all of this in a good way or better way exists.
Ok! I tell you how i solved this problem. Please, tell me your opinion.
I created a custom deserializer (here i create concretes instances). Here is the code:
#RequestMapping(value = "/pages/save",method=RequestMethod.GET)
public #ResponseBody String save(#RequestParam String widgetsList){
GsonBuilder gson = new GsonBuilder();
// register the custom deserializer for my WidgetAdapterClass
gson.registerTypeAdapter(WidgetAdapter.class, new WidgetDeserialization());
Type listType = new TypeToken<List<WidgetAdapter>>() {}.getType();
// create gson an deserialize object
List<WidgetAdapter> adapters = gson.create().fromJson( widgetsList, listType);
// just for testing proposes
for(WidgetAdapter a :adapters){
System.out.println(a.getWidth());
}
return new Gson().toJson(new ActionResult("Ok"));
}
the concrete deserializer
public class WidgetDeserialization implements JsonDeserializer<WidgetAdapter> {
/***
* factory method for custom WidgetAdapter
* #param json
* #return WidgetAdapter
*/
private WidgetAdapter getWidget(JsonObject json){
WidgetAdapter adapter = null;
//obtain widget class. Util for instanciate concrete class
String className = json.get("className").getAsString();
// create concrete classes and set concrete atributes
if("text".equals(className)){
adapter = new TextWidgetAdapter(json.get("text").getAsString());
}else if("youtube".equals(className)){
adapter = new YoutubeWidgetAdapter(json.get("videos").getAsString());
}
// if adapter is created common atributes are set
if(adapter!=null){
adapter.setHeight(json.get("height").getAsInt());
adapter.setWidth(json.get("width").getAsInt());
adapter.setX(json.get("x").getAsInt());
adapter.setY(json.get("y").getAsInt());
}
return adapter;
}
#Override
public WidgetAdapter deserialize(JsonElement element, Type arg1,
JsonDeserializationContext arg2) throws JsonParseException {
JsonObject obj = element.getAsJsonObject();
return getWidget(obj);
}
}
I hope it helps