Jersey web service with date or primitive as parameter - java

I have a jersey web service that takes post data and maps it (using jackson) to a data structure that looks like
public class MyObject {
String name
Object dateOrPrimitive
}
On the javascript client that calls the web service, it could send an object that could take either of the following forms
{ name : "Jeff", dateOrPrimitive : "someOtherString" }
{ name : "Jeff", dateOrPrimitive : new Date() }
If the dateOrPrimitive field has a date in it, it is deserialized into a string representation of the date. But what I would like to do is deserialize it to a date if it is a valid date string.
I wrote a custom deserializer that checks if the value is a valid date and returns a date if it is and a primitive otherwise, but I was wondering if there is already a built in a way to do this.

No there isn't such a thing in Jackson. Your custom deserializer is the way to go on this. Personnaly I would have two different properties, one a Date and the other a primitive, but I'm guessing you don't have control over the format of the Json.

Related

Spring Data MongoDB Field Converter: Any way to pass a parameter?

When our application is loading a DBOject/Document instance from our MongoDB, we need to convert all of the UTC dates in it into ZoneDateTime values using the zoneIdName, which is within the DBObject/Document instance. We have a lot of Date fields in the DBObject, so I'd like to avoid having to implement a DBOject level Spring Data MongoDB Converter.
Is it possible to use a DBOject field level Spring Data MongoDB Converter, such as the following, which uses a field in the DBObject (i.e. zoneIdName), to be able to perform the conversion to a ZoneDateTime? If not, I will have to implement an object-level Converter, but it will be tedious...
Thank you for your interest and time.
class ZonedDateTimeReadConverter :
Converter<Date, ZonedDateTime> {
override fun convert(date: Date): ZonedDateTime {
// Need to replace "America/LosAngeles" with
// a value from a field in the object being processed.
return date.toInstant().atZone(ZoneId.of("America/LosAngeles"))
}
}
seems that converter for whole object is only option

Jsonkey in Api Response has $

I'm basically using retrofit to create a request to a server, however the date is stored in mongodb and the request returns a response that contiants $date, is there a way to retrieve it?
I'm assuming from the question title that you mean there's a json key with a dollar sign and I'll assume you're using Gson too, because that's common with Retrofit. If so, then you're looking for SerializedName
This annotation lets you specify the name in the json for the key. So in your case you'd want to add it to your model. Something like:
public class Foo {
#SerializedName("$date")
private String date;
}
in kotlin:
data class foo(
#SerializedName("\$date")
val date: String)
This annotation is used by Gson to serialize and deserialize the object into and from json.
I'm sure other libraries that can be plugged into retrofit have something similar.
Also note that on Android this annotation is very handy, because of the obfuscation tools. Usually the models are obfuscated and the variable names change. If you want to keep the right names then this is an approach to it.

how to convert json property like "oData.type" to java object [duplicate]

What is the basic purpose of #SerializedName annotation in Android using Gson?
Give me some different examples. I can't understand the main purpose of using it.
Java class example,
public class Person {
#SerializedName("name")
private String personName;
#SerializedName("bd")
private String birthDate;
}
This class has two fields that represent the person name and birth date of a person. These fields are annotated with the #SerializedName annotation. The parameter (value) of this annotation is the name to be used when serialising and deserialising objects. For example, the Java field personName is represented as name in JSON.
JSON Example,
{
"name":"chintan",
"bd":"01-01-1990"
}
There are already few answers here,but I would like to add that if you are using ProGuard to Obfuscate your code & don't use #SerializedName("name") in your model class, then your GSON won't work. Because due to obfuscation, your variable names might have changed from String name to String a resulting into broken GSON parsing as GSON will look for key a into json & it will fail.
By specifying #SerializedName, GSON will not look in json based on variable name & will just use specified #SerializedName.
Of Course you can tell proguard to not obfuscate your model, but if you would like to have model obfuscated, then you must specify #SerializedName
Using #SerializedName you are actually telling the Parser when receiving a callback from the server i.e. of a Json format:
{
"name":"John Doe",
}
that when Serializing or Deserializing an object to instead of searching for a key named: "userName", in the Json response, to search for "name".
#SerializedName("name")
var userName: String,
This is good because you may have a model that you would like it to have its members being called with whatever you like.
You can instruct Proguard to not obfuscate your data classes by specifying #Keep on top of the class. This will neither remove nor obfuscate your class. No need to add #SerializedName to each and every field explicitly if the field name is similar to the Json key being used for it.
Let's say in a real-world scenario, your backend dev is giving you this response for an API request you make
{
"name":"John Doe",
"id":"1478"
}
Now, in the data class you make to handle this, there might be chances you want to specify a different variable name at Android side for the fields "name" and "id" that you are getting from backend.
#SerializedName comes to rescue here.
You just need to specify the actual key value you will be getting from backend in the #SerializedName (which will be used to serialize and deserialize) and then you can use a variable name of your choice that stores that value received from the operation.
For example, for the JSON I mentioned earlier, here is how its data class will look like:
data class User(
#SerializedName("name") val userName: String,
#SerializedName("id") val userId: Int
)
Here name, id is used in #SerializedName because it's the backend key.
But I have used userName, userId to store those values.

Is there any way to create JSON object with keys as upper case?

Project: Android app using REST web service
Using:
Client - Volley
Server API - Jersey
Converter: Gson
This is my first time asking a question here, and i will provide my way of "evading" this code convention. Since i am working on a project where POJO fields are already defined as upper-case (sadly, i cant change that), i had to find a way to fix JSON string and convert it to an instance of uppercase POJO.
So basicaly its: client POJO <--> json object converted to/from gson <--> server POJO
So, lets say that i have a field in Users.class
String USERNAME;
When Jersey sends an instance of via #Produces, it follows the convention of creating JSON and sends an object
{"username": "random_name"}
When it gets converted from JSON via gson.fromJSON, an instance of a client's POJO will get null value for that field (obviously because field is in lower-case in JSONObject).
This is how i managed it by using a method that parses JSONObject and puts each key as upper-case:
public static String fixJSONObject(JSONObject obj) {
String jsonString = obj.toString();
for(int i = 0; i<obj.names().length(); i++){
try{
obj.names().getString(i).toUpperCase());
jsonString=jsonString.replace(obj.names().getString(i),
obj.names().getString(i).toUpperCase());
} catch(JSONException e) {
e.printStackTrace();
}
}
return jsonString;
}
And luckily since gson.fromJSON() requires String (not a JSONObject) as a parameter besides Class, i managed to solve the problem this way.
So, my question would be: Is there any elegant way of making JSON ignore that code convention and create a JSON object with an exact field? In this case:
{"USERNAME": "random_name"}
Jersey uses JAXB internally to marshall beans to xml/json. So you can always use #XmlElement annotation and use name attribute to set the attribute name to be used for marshalling
#XmlElement(name="USERNAME")
String USERNAME;
Just use annotation com.google.gson.annotations.SerializedName
Add in class Users.java:
#SerializedName("username")
String USERNAME;

What is the basic purpose of #SerializedName annotation in Android using Gson

What is the basic purpose of #SerializedName annotation in Android using Gson?
Give me some different examples. I can't understand the main purpose of using it.
Java class example,
public class Person {
#SerializedName("name")
private String personName;
#SerializedName("bd")
private String birthDate;
}
This class has two fields that represent the person name and birth date of a person. These fields are annotated with the #SerializedName annotation. The parameter (value) of this annotation is the name to be used when serialising and deserialising objects. For example, the Java field personName is represented as name in JSON.
JSON Example,
{
"name":"chintan",
"bd":"01-01-1990"
}
There are already few answers here,but I would like to add that if you are using ProGuard to Obfuscate your code & don't use #SerializedName("name") in your model class, then your GSON won't work. Because due to obfuscation, your variable names might have changed from String name to String a resulting into broken GSON parsing as GSON will look for key a into json & it will fail.
By specifying #SerializedName, GSON will not look in json based on variable name & will just use specified #SerializedName.
Of Course you can tell proguard to not obfuscate your model, but if you would like to have model obfuscated, then you must specify #SerializedName
Using #SerializedName you are actually telling the Parser when receiving a callback from the server i.e. of a Json format:
{
"name":"John Doe",
}
that when Serializing or Deserializing an object to instead of searching for a key named: "userName", in the Json response, to search for "name".
#SerializedName("name")
var userName: String,
This is good because you may have a model that you would like it to have its members being called with whatever you like.
You can instruct Proguard to not obfuscate your data classes by specifying #Keep on top of the class. This will neither remove nor obfuscate your class. No need to add #SerializedName to each and every field explicitly if the field name is similar to the Json key being used for it.
Let's say in a real-world scenario, your backend dev is giving you this response for an API request you make
{
"name":"John Doe",
"id":"1478"
}
Now, in the data class you make to handle this, there might be chances you want to specify a different variable name at Android side for the fields "name" and "id" that you are getting from backend.
#SerializedName comes to rescue here.
You just need to specify the actual key value you will be getting from backend in the #SerializedName (which will be used to serialize and deserialize) and then you can use a variable name of your choice that stores that value received from the operation.
For example, for the JSON I mentioned earlier, here is how its data class will look like:
data class User(
#SerializedName("name") val userName: String,
#SerializedName("id") val userId: Int
)
Here name, id is used in #SerializedName because it's the backend key.
But I have used userName, userId to store those values.

Categories

Resources