Java JSON deserialization without predefining everything - java

I realize this has probably been asked a hundred times but I have searched a lot and can't find specifically what I'm looking for.
Here is what I'd like. Given a string data, I'd like to deserialize into an object obj that doesn't have all the fields predefined. I'd like to just be able to ask for the fields I want such as obj.getString("stringFieldName") or obj.getInt("intFieldName"). I already have gson being used for other things so if it is possible with gson that would be great although not opposed to using another library.

The 'standard' Android JSON library (since API 1) already provides such untyped access.
See JSONObject, eg. getInt:
Returns the value mapped by name if it exists and is an int or can be coerced to an int, or throws otherwise.
Unless needing the JSON mapped onto a 'native' Java collection type this is probably the simplest way to achieve the request. It doesn't require any additional libraries.

With Jackson library you can annotate data model class with
#JsonIgnoreProperties(ignoreUnknown = true)
and the jacksonconverter will just parse only these fields that you defined. Other will be ignored.

Have you tried using Retrofit from Square? It works with GSON and Java Annotations and it's super easy to set up.

Related

How to make a data field optional (not required) in JAX-RS?

I have a RESTapi written using Jersey Framework. Along with it there is a POJO class. Now, my need is how do I make a particular field optional in my POJO so that the api will work regardless of that optional field? I want the API should work in both the cases, i.e
if I give that optional parameter then also,
if I don't give then also it should work.
Java 8's Optional was mainly intended for return values from methods, and not for data properties of Java classes(POJO), as described in Optional in Java SE 8:
Of course, people will do what they want. But we did have a clear
intention when adding this feature, and it was not to be a general
purpose Maybe or Some type, as much as many people would have liked us
to do so. Our intention was to provide a limited mechanism for library
method return types where there needed to be a clear way to represent
"no result", and using null for such was overwhelmingly likely to
cause errors.
The key here is the focus on use as a return type. The class is
definitively not intended for use as a property of a Java Bean.
Witness to this is that Optional does not implement Serializable,
which is generally necessary for widespread use as a property of an
object.
[credits] : https://blog.joda.org/2014/11/optional-in-java-se-8.html
I'm guessing you are referring to the serialisation of fields in your POJO. Since you have not stated which version of jackson you are using, you'll have to use one of these annotations to allow nulls:
Can be used on either class or getter:
#JsonInclude(Include.NON_NULL)
If you are using Jackson <2.x, use this:
#JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)

How can I generate a JSON Schema from a Java class with generics when I am only given a string?

I am working on a project where I need to generate JSON schemas for all of the objects that are returned from my API.
I am given a String such as:
"com.example.CustomListing<MyClass>"
My goal is to create a schema for CustomListing and insert a $ref to MyClass in all the places it is used in CustomListing.
Jackson offers a way to create schemas from generics here but I need to have Class object for that generic type.
I can create a generic Class object using a method here but it requires me to know the type ahead of time, which I do not.
How can I get a Class<CustomListing<MyClass>> when I am only given the String "com.example.CustomListing<MyClass>"?
EDIT: I am creating these schemas in a JavaDoc doclet, so I am working at compile time, hence the limitations.
I think I have found a direction to go for the solution. I am using ObjectMapper from Jackson which allows me to configure modules to process any given type. I believe I can register some to deal with a generic (such as <T>) and it would know that in this case <T> would be referencing MyClass instead and insert the $ref.

simple method/extendable class to make my toString method of a POJO output json like output?

I have a number of pojos which are being used for a jersey client to be filled with the JSON data from a restful call. The client is reading in json and filling these objects using the JacksonJsonProvider. I'm not using any annotations, the variable names are equal to the json coming in.
I would like the toStrng methods for these PoJos to automatically output a representation of the json they represent, without my having to manually write each toString. Since these are basic POJO which are structured in a simlpe tree format it should be realatively easy to output these pojo as json in the toString method. In fact I know I could use reflection to do this myself in some parent/abstract class if I felt like it. However, it feels like I shouldn't have to do this by hand. Is there already some method out there that will do this for me I can use instead?
I don't insist that the output be json, though that would be preferable, but any similar method of visualizing the variables automatically without my manually writing it would be fine.
Thanks
If you use Google GSON you can serialize objects into JSON. Your toString() would then look something like:
public String toString() {
return StaticLib.GSON.toJson(this);
}
A GSON object can be shared across all objects, hence my inclusion of this mystery StaticLib class. You can find the correct name or place for that in your own project I'm sure.

Map JSON Response to POJO (with different names)

I know there are numerous posts out there for a similar problem, but mine seems to be a bit different. I am reading in a bunch of JSON and would like to build POJO from it, but I don't want to use the names of the JSON result. Is there a way to "map" the element names in JSON to the attributes in my POJOs (using gson or Jackson maybe)?
It's worth mentioning this application is being built for Android.
Thanks in advance!
If you're using Gson, you can append an attribute to your objects, like so:
#SerializedName("ServicesResult")
public String services;
Where "ServicesResult" is the actual name of the element in the JSON.
With Jackson, you have multiple options:
Use #JsonProperty("name") annotation to indicate name to use in JSON, add directly or use mix-in annotations (external)
Specify PropertyNamingStrategy to convert from "Java name" to "JSON name" (there is default java<->c-style converter bundled with 1.9)
Modify AnnotationIntrospector to change the name using some other mechanism than annotations
Jackson will also interpret the Basic package javax.xml.bind.annotation
If you use those annotations you can readily move between Json/XML

Convert JSON style properties names to Java CamelCase names with GSON

I'm using GSON to convert JSON data I get to a Java object. It works pretty well in all my tests.
The problem is that our real objects have some properties named like is_online. GSON only maps them if they are named totally equal, it would be nice to have GSON convert the names to Java camel case isOnline.
It seems this is possible while creating the JSON data, camel case is converted to underscore separated words in JSON. But I can't find a way to specify this the other way round.
I have found the following setting works perfect when reading json with underscored attributes and using camelcasing in my models.
Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.create()
You can use the SerializedName annotation:
#SerializedName("field_name_in_json")
private final String fieldNameInJava;
Note: When you have set a FieldNamingPolicy already, SerializedName will overwrite its settings for that specific field (quite handy for special cases).
Bear in mind your example is an edge case. If you have a property 'foo' its getter should be named 'getFoo', and if you have a property named 'foo_bar' its getter should be named 'getFooBar', however, in your example you're mapping a boolean and booleans have special case naming conventions in java. A primitive boolean property named online should have a getter named 'isOnline', NOT 'getOnline' or even worse, 'getIsOnline'. A boolean wrapper object (i.e. Boolean) should not follow this special case and a property named 'online' should have a getter named 'getOnline'.
Hence, having boolean properties with 'is' in the name is an edge case, where you'll want to strip out this particular prefix during your conversion. In the reverse direction, your code may want to inspect the json object for both a raw property name as well as a 'is_XXX' version.
I think what you want is here. Using annotations you can tell GSON that the mySuperCoolField is actually called this_field_is_fun in the JSON and it will unpack it correctly. At least I think it works for deserialization too.
If that doesn't work, you can use custom JsonSerializer/JsonDeserializers, which work great, but you have to update them for changes in your class (like when you add a field). You lose the auto-magic.
The easiest thing to do (which would be ugly, but very clean and simple if the first suggestion doesn't work) would be to simply name the field in a way to make GSON happy, and add extra accessor methods with the names you like, e.g.
public boolean isXXX() {return this.is_XXX;}

Categories

Resources