DynamoDBMarshaller for generic list - java

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);

Related

JsonDeserializer is not working with gson

I have a list(list contains the requiredFields and this list can get the dynamic data from text file) and I have api response jsonData.
Now, I need to extract the data from api(jsonData) response, only the required fields(what list contained fields). All this need to be done using gson serializer
public class EDSJsonSerializer implements JsonDeserializer {
final list<String>; // list can be populated by reading data from text
file
//ex: list<Strin> is : [ab,bc]
#Override
public JsonElement deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
jsonElement => {"ab":"234234","bc":"wrwerewe","ww":"345fsd","456":"dfgdfg"}
final Map map = new HahMap();
map should contain only 2 elements {"ab":"234234","bc":"wrwerewe"}
map can be populated with list above given as keys and values from json passed
}
}
final String json = ""; // json is the api response string
final GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Map.class, new EDSJsonSerializer());
final Gson gson = builder.create();
final String map = gson.toJson(json);
it is not working as expected and not throwing any error/exception.
Please help me on this
Thanks,
Syamala.
Firstly 456 is not a valid Java class field name. It might be one reason of your problems even you might never use it from Json.
Secondly you migh better use ExclusionStrategy to decide which fields to de- & serialize.
In your case something like:
#RequiredArgsConstructor
public class ExcludeUnlistedFields implements ExclusionStrategy {
#NonNull
private Set<String> fieldsToInclude;
#Override
public boolean shouldSkipField(FieldAttributes f) {
// if you need to restrict to specific a class/classes
// add the checks here also
return ! fieldsToInclude.contains(f.getName());
}
#Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
}
and use it like:
Set<String> fieldsToInclude = new HashSet<>(Arrays.asList("ab", "bc"));
ExclusionStrategy es = new ExcludeUnlistedFields(fieldsToInclude);
Gson gson = new GsonBuilder().setPrettyPrinting()
.addDeserializationExclusionStrategy(es).create();

How to create list with unknown object in java

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;
}

How to add two different objects into a single object

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*/
}

parameters and inheritance in spring-mvc via json

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

GSON and Generic types

I've come across a problem of using Gson library and generic types(my types and collections). However they have an answer how to solve this problem, I don't think it's appropriate to write a specific message converter for the every type I've already implemented and I'll implement.
What I did is:
Implemented my own message converter:
public class SuperHttpMessageConverter extends AbstractHttpMessageConverter<Object> {
private final Charset charset;
private final Gson gson;
public CostomHttpMC_1(MediaType mediaType, String charset) {
super(mediaType);
this.charset = Charset.forName(charset);
gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
}
#Override
protected Object readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException {
String jsonString = FileCopyUtils.copyToString(new InputStreamReader(inputMessage.getBody(), charset));
return gson.fromJson(jsonString, clazz);
}
#Override
protected Long getContentLength(Object obj, MediaType contentType) {
try {
String jsonString = gson.toJson(obj);
return (long) jsonString.getBytes(charset.name()).length;
} catch (UnsupportedEncodingException ex) {
throw new InternalError(ex.getMessage());
}
}
#Override
protected void writeInternal(Object obj, HttpOutputMessage outputMessage) throws IOException {
String jsonString = gson.toJson(obj);
FileCopyUtils.copy(jsonString, new OutputStreamWriter(outputMessage.getBody(), charset));
}
#Override
public boolean supports(Class<?> clazz) {
return true;
}
}
It works well until I try to send a collection like List<String> or some Type<T>.
Gson has the solutions here: http://sites.google.com/site/gson/gson-user-guide
Also I tried the json-lib library yesterday. What I don't like about it is in-depth scanning of all objects which I have in the hierarchy. I tried to change the cycle detection strategy from CycleDetectionStrategy.STRICT to CycleDetectionStrategy.LENIENT, it didn't help at all!
#Override
protected void writeInternal(Object obj, HttpOutputMessage outputMessage) throws IOException {
JsonConfig jsonConfig = new JsonConfig();
jsonConfig.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
String jsonString = JSONObject.fromObject( obj ).toString();
FileCopyUtils.copy(jsonString, new OutputStreamWriter(outputMessage.getBody(), charset));
}
Finally, a work-around for the generic collection's problem was found out: changing from ArrayList to simple array helps to do serialization and deserialization. To be more specific you have to do it in a web-service, which you use in an application.
#RequestMapping(value = "/country/info/{code}")
public void info(#PathVariable("code") String code, Model model) {
//list
StuffImpl[] stuffList= new StuffImpl[0]; <-- this is the array I used!
stuffList= restTemplate.getForObject("http://localhost:8084/yourApp/restService/stuff", stuffList.getClass());
model.addAttribute("stuffList", stuffList);
}
So this approach is working good.
I failed to found out what a solution for generic type is. I really do hate an idea to write a new converter every time I implement a new generic type.
If you know any possible solution I'd appreciate your help a lot!
I'd be on the cloud nine if anyone could help me :)
L.
There are some methods where you can pass java.lang.reflect.Type. These methods are useful if the specified object is a generic type, e.g.:
Gson gson = new GsonBuilder().create();
List<String> names = new ArrayList<String>();
names.add("Foo");
names.add("Bar");
// marshal
String jsonLiteral = gson.toJson(names);
System.out.println(jsonLiteral);
// unmarshal
List<String> names2;
Type type = new TypeToken<List<String>>() {
}.getType();
names2 = gson.fromJson(jsonLiteral, type);
System.out.println(names2.get(0));
System.out.println(names2.get(1));
This will output:
["Foo","Bar"]
Foo
Bar

Categories

Resources