Autobean returns an autobean after using as() - java

in my gwt project i am sending objects with the gwt channel api to the client and use Autobean to encode and decode those objects. everything works fine, i receive a valid json string on the client and can decode that json string to the AutoBean back again. only the autobean.as() does not return anything different than the autobean itself.
IContactDto and ContactDto just contain getters and setters. and this is the facbory i wrote
AutoBeanFactory
public interface DtoFactory extends AutoBeanFactory{
AutoBean<IContactDto> contactDto(IContactDto contactDto);
}
Server-side code
DtoFactory dtoFactory = AutoBeanFactorySource.create(DtoFactory.class);
AutoBean<IContactDto> iContactDto = dtoFactory.contactDto(contactDto);
String sJson = AutoBeanCodex.encode(autoBean).getPayload();
// sending this json to the client
Client-side code
this is the code i use for decoding the valid json string
// sJson string looks like {"id":"6473924464345088", "lastUpdate":"1475914369346", "fullName":"testName1","givenName":"testName2"}
DtoFactory factory = GWT.create(DtoFactory.class);
AutoBean<IContactDto> autoBean = AutoBeanCodex.decode(factory, IContactDto.class, sJson); // debugger: IContactDtoAutoBean_1_g$
IContactDto iDto = autoBean.as(); // debugger still shows IContactDtoAutoBean$1_1_g$
i can actually use the getters and setters of this object, but as soon as i try continue to work this those objects i get a problem with the type signature.
any ideas how i can get the object i encoded back again?

AutoBean#as() returns a “proxy implementation of the T interface which will delegate to the underlying wrapped object, if any.” (source: javadoc), it will never return the wrapped object itself.
Moreover, when deserializing from JSON, there's no wrapped object, a new autobean is created "from scratch" and then filled with JSON (it actually directly wraps a Splittable from the parsed JSON: super-lightweight, just a thin typesafe wrapper around a JS object –or a org.json.JSONObject when not in the browser.)

Related

GSON: How to decode from json to Model ignoring an Object?

I have a Model consisting in a main Manager class, which has some variables, for example name but also has a big object called data. For a special case I want to pass from json to Model with Gson but ignoring the data Object of the json (for the normal case I will decode completely all the objects of the json).
I need to do this without anotations and without transient, just adding a deserializing rule to exclude Data class in case I want to do it.
How can I specify ad decode time that I want to ignore a class?
My model:
public class Manager{
String name;
Data data;
}
public class Data{
String dummy;
String dummy2;
}
Json sample:
{"manager":{"name":"testname","data":{"dummy":"testname", "dummy2":"testname2"}}}
Code sample that decodes all:
GsonBuilder gsonBuilder = new GsonBuilder();
new GraphAdapterBuilder()
.addType(Data.class)
.addType(Manager.class)
.registerOn(gsonBuilder);
Gson gson = gsonBuilder.create();
Manager manager = gson.fromJson(json, Manager.class);
Fortunately for you, I banged my head last week to sort out a derivative of what you're trying to achieve. So as i mention in this post there is a little trick in the release version that maybe suite what are you trying to do:
Apparently the toString() method inside the parsed class is needed to
make the Gson library work.
The toString() method expose the class to the serialization.
Having said that if you use a release version and don't add any proguard rules you can use the following method to exclude data:
#Override
public String toString() {
return "Manager{" +
"name='" + name + '\'}';
}

Jackson Deserializer - inject key:value pairs if not present in serialized data

I save the payload of events as JSON string into a database.
To only have one version of the events in code while still being able to read old events I want to "upcast" the serialized data before deserialization.
I thought about something like this:
public Object deserialize(String data, Class<?> clazz) throws IOException {
data = upcaster.upcast(data, clazz);
return objectMapper.readValue(data, clazz);
}
But this means I transform the string into some JSON object twice. Once for upcasting the data and once inside the standard jackson mapper.
Is there a way to customize jackson between building the json-object and building my event object?
Something like:
#override
updateData(clazz, jsonData) {
if(clazz.equals(SpecificEvent.class)) {
if(!jsonData.containsKey("addedInfo")) {
jsonData.put("addedInfo", "foo");
}
}
}
Alternatively, I could add my own deserializer that changes the given JSON data before calling the standard deserializer I guess?
What's the normal way of doing something like this with jackson?
One option is custom deserialization with a dedicated deserializer class (per your own class). You would then have to maintain the deserializer class to make sure that it provides any missing data.
It should work for a handful of classes, if you have a lot then there might be better ways.

Java Object to JSON Conversion

I have a Java object as below
public class Command {
private String cmd;
private Object data;
}
I want JSON Conversion of this Object to look as below
{"cmd":"getorder","data":{"when":"today"}}
How do I do this without changing the Class definition?
I know how to use GSON or Jackson library. I am having trouble assigning values to or initializing (Object) data above, so that it properly converts to {"when":"today"} when I use those libraries.
Thanks
You can try Gson library
it's very easy to use and it can do the reverse operation as well
Depending on your needs you might consider to add a handwritten json formatter for your class (of yourse this interferes with your demand to not change the class definition) but in fact it gives you max flexibility without 3rd party dependencies. If you strictly let all your Objects overwrite toString() to give json formatted string representation you could e.g.
String toString() {
StringBuffer result = new StringBuffer();
result.add("{ \"cmd\":" + this.cmd);
result.add(",");
result.add( \"data\":" + data.toString());
result.add("}");
return result.toString();
}
In case your need to not change the class definition appears more important than the mentioned advanteges there is a a nice json library avaialble on code.google.com named "simple json" ( https://code.google.com/p/json-simple/ ).

Bean with generic field that is not always used

This is a curious situation: I have a bean like this that store some information and I need generics, because the field "data" can contain different types of data.
public class Request<T> {
private String name;
private Integer code;
private T data;
/* Getter and setters */
}
The fact is that "data" is not always used and sometimes it can be null. And if I want to avoid raw types I have to define a type anyway, like this:
Request<Object> req = ....
Is there a better way of doing that, where I can both 1) Avoid raw types 2) Have a generic data field in my request objects ???
If you don't mind the request type, use Request<?> in your declaration.
If the request is empty (meaning there is no type, which can be set as data), declare it as Request<Void>
You could always use the Void type, e.g.
Request<Void> req = ...
or a wildcard:
Request<?> req = ...
Maybe you should consider to change object hierarhy. If you dont use data in some cases, maybe you should have two objects:
class Request {
private String name;
private Integer code;
/* Getter and setters */
}
class DataRequest<T> extends Request {
private T data;
/* Getter and setters */
}
and use:
Request req1 = new Request();
Request req2 = new DataRequest<String>();
Maybe you should think in a different way: In your case a Request not always has associated data. Modelling this with null-values is a bad decision, because you have to check for this every time you want to use your data. At some point you want to handle Request without data in a different way then Request with data.
Maybe you should make your Request to an interface containing Methods like getName() and getCode() and create two concrete classes RequestWithData<T> and RequestWithoutData implementing this interface. Then you can check on creation of an RequestWithData<T>-instance, if a non-null data is provided. Furthermore, you can express in your method signature that you require a Request with data or without data. This leads to a more clean design and avoids your problem.
Use the new 'Optional' type in Java 8. It was made specifically for cases like these. If you cannot, for whatever reason, use Java 8 yet, the Google Guava library also implements that type. Check this example : https://gist.github.com/9833966

Java type conversion where types are not known until runtime

I'm trying to write a data access layer for an AJAX web project. This DAL has to convert data coming in via an AJAX servlet to objects that can be passed to a PreparedStatement for execution.
Data in the AJAX servlet, retrieved by using HttpServletRequest.getParameter(...), come in as strings.
In each data class, I have a known set of fields as well as their data types, e.g. CustomerId(integer), CustomerName(string).
I can of course write a method in the Customer class to handle the conversion, but this means I have to do it for every data object's class. I would much rather have a generic method that does conversion, e.g.
Object convert(String value, Class<?> targetType) { ... }
Can anyone point me in the right direction?
Create an utility class with all conversion methods you would like to use. Inside its static initializer, make use of reflection to collect all those methods by parameter type and return type in a map. Then, in the convert() method just pick the method which suits the given source and target type and invoke it. Make use of generics to fix the return type to be the same as the target type:
public static <T> T convert(Object from, Class<T> to)
You can find an example in this article.
But as bmargulies pointed out, JSON is also an interesting option. You could let ajax to send all parameters as one JSON string. Then, you can use a JSON-to-Javabean converter like Google Gson to convert the JSON string to a fullworthy Javabean like Customer. It'll be as simple as:
String jsondata = request.getParameter("jsondata");
Customer customer = new Gson().fromJson(jsondata, Customer.class);
// ...
See also this answer for another example.
There are JSON libraries that will do data type conversion. Jackson is one. Or, you could code the whole think using a JAX-RS service framework instead of a raw servlet, and it will take care of all this for you. Apache CXF is one framework that contains this support. Since you are asking for a generic solution, why not use one that's already out there.
We do this exact thing using a plethora of static converters in a utility class. It isn't elegant but it sure is easy and effective.
class Util {
public static Long StringToLong(String s) { ... }
public static Integer StringToInt(String s) { ... }
public static Date StringToDate(String s) { ... }
public static Date StringToDateYYMMDD(String s) { ... }
public static BigDecimal StringToBigDecimal(String s) { ... }
// etc ad naseum
}
Since you want to use the parameters in your PreparedStatement, why do you have to convert them at all?
When using setString(index, parameter) SQL will be happy to do the conversion for you.
Thus the only thing you might want to do is some kind of validation that the input is really valid (or you could even leave this part to your SQL engine which will throw an exception if it doesn't understand you.

Categories

Resources