What pattern should I use for date format 1418805300000-0100 ? (Timestamp and timezone)
GsonBuilder().setDateFormat("?????????????-Z")
Solution:
create new GSON with adapters
private static Gson createGson(){
return new GsonBuilder().disableHtmlEscaping()
.registerTypeHierarchyAdapter(Date.class, new DateTimeSerializer())
.registerTypeHierarchyAdapter(Date.class, new DateTimeDeserializer())
.create();
}
public static MyClass fromJson(String json) {
return createGson().fromJson(json, MyClass.class);
}
public String toJson() {
return createGson().toJson(this);
}
JSON Serializer
private static class DateTimeSerializer implements JsonSerializer<Date> {
#Override
public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
// hodgie code
return new JsonPrimitive(src.getTime() + new SimpleDateFormat("Z").format(src));
}
}
Deserializer
private static class DateTimeDeserializer implements JsonDeserializer<Date> {
#Override
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
// hodgie code
return new Date(Long.valueOf((json).getAsString().substring(0, 13)));
}
}
GsonBuilder#setDateFormat(String) uses the String provided as an argument for creating SimpleDateFormat instances. SimpleDateFormat does not provide any patterns for generating a timestamp. You won't be able to achieve what you want with setDateFormat. A custom TypeAdapter seems appropriate.
Related
I have a problem trying to deserialize a gson LocalDate.
I have the next 2 adaptors:
public class LocalDateSerializer implements JsonSerializer < LocalDate > {
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d-MMM-yyyy");
#Override
public JsonElement serialize(LocalDate localDate, Type srcType, JsonSerializationContext context) {
return new JsonPrimitive(formatter.format(localDate));
}
}
and
public class LocalDateDeserializer implements JsonDeserializer < LocalDate > {
#Override
public LocalDate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return LocalDate.parse(json.getAsString(),
DateTimeFormatter.ofPattern("d-MMM-yyyy").withLocale(Locale.ENGLISH));
}
}
I try to make a simple Serialization of an object "Task" which have a field starttime of LocalDate type.
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(LocalDate.class, new LocalDateSerializer());
gsonBuilder.registerTypeAdapter(LocalDate.class, new LocalDateDeserializer());
Gson gson = gsonBuilder.setPrettyPrinting().create();
LocalDate now=LocalDate.now();
Task task=new Task();
task.setID(1);
task.setDuration(2);
task.setID_Proiect(1);
task.setStarttime(now);
JSONObject json=new JSONObject(task);
String aux1=gson.toJson(json);
System.out.println(aux1);
Task t2=gson.fromJson(aux1,Task.class);
I receive the error
Failed making field 'java.time.LocalDateTime#date' accessible; either
change its visibility or write a custom TypeAdapter for its declaring
type
Can you tell me what is wrong with this code? I know it is probably a noobie question but i rly need help to improve my skills. Ty
I've got a json file which has got a Date field. I'm transforming this to a required Date format(dd/MM/yyyy) using JsonDeserializer and registering the class as a TypeAdapter in GsonBuilder. Now, I want to transform this field to different date formats(say ISO8601) for different use cases. Instead of creating new JsonDeserializer's for different date formats, Is there anyway I can pass date format as one of the parameters to JsonSerializer class to make it extensible.
Deserializer class:
public class DateDeserializer implements JsonDeserializer<Date> {
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd/MM/yyyy");
#Override
public Date deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) {
String dateString = jsonElement.getAsString();
if (!StringUtils.isEmpty(dateString)) {
try {
return DATE_FORMAT.parse(dateString);
} catch (ParseException e) {
}
}
}
GsonBuilder:
public static final Gson GSON = new GsonBuilder()
.registerTypeAdapter(Date.class, new DateDeserializer())
.serializeNulls()
.create();
I have created a deserialization, that whenever it see the String "nil", it will return null.
private static Gson createCustomGson() {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(String.class, new JsonDeserializer<String>() {
#Override
public String deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
return (json.getAsString().equals("nil")) ? null : json.getAsString();
}
});
return gsonBuilder.create();
}
It works good except that, I want to add an exception where for the field "Keyword" that store a List, I don't want to eliminate nil to return null, but retain the String. How to add the exception for "Keyword"?
My Keyword class is of the below type
public class KeywordListing implements Serializable {
List<String> keys;
}
Found a solution. It's by adding another TypeAdapter to use back the default deserizliation from Gson instead as below.
private static Gson createCustomGson() {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(String.class, new JsonDeserializer<String>() {
#Override
public String deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
return (json.getAsString().equals("nil")) ? null : json.getAsString();
}
});
gsonBuilder.registerTypeAdapter(KeywordListing.class, new JsonDeserializer< KeywordListing >() {
#Override
public KeywordListing deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
return new Gson().fromJson(json, KeywordListing.class);
}
});
return gsonBuilder.create();
}
Let me know if there's a shorter answer than what I got above.
I have one class User, I received JSON (for User class) from system1 and I should read info , validate then forward to system2, I can't touch these 2 systems, the problem is the names of keys are different, I want to differentiate between deserialized and serialized name
received JSON is :
{"userId":"user1","pwd":"123456","country":"US"}
"{"username":"user1","password":"123456","country":"US"}"
But the sent should be like this
I am using Gson lib, and this is my code:
User class:
class User implements Cloneable {
#SerializedName("username")
private String username ;
#SerializedName("password")
private String password ;
#SerializedName("country")
private String country ;
}
TestJson class
class TestJson {
private static GsonBuilder gsonBuilder;
private static Gson gson;
public static Object fromJson(String json, Class clz) {
gson = new Gson();
return gson.fromJson(json, clz);
}
public static String toJson(Object obj) {
gsonBuilder = new GsonBuilder();
gson = gsonBuilder.create();
String json = gson.toJson(obj);
return json;
}
public static void main(String[] args) {
String json2 = "{\"userId\":\"user1\",\"pwd\":\"123456\",\"country\":\"US\"}";
User user = (User) TestJson.fromJson(json2, User.class);
System.out.println(user.getPassword());
User u = new User("user1","123456","US");
String json1 = TestJson.toJson(u);
System.out.println(json1);
}
}
If there are alternative names of field just use alternate param of #SerializedName
public class User {
#SerializedName(value="username", alternate={"userId", "useriD"})
private String username ;
...
}
You can create custom serializer/deserializer for this purpose.
Serializer:
public class UserSerializer implements JsonSerializer<User> {
#Override public JsonElement serialize(User obj, Type type, JsonSerializationContext jsonSerializationContext) {
..........
}
}
Deserializer:
public class UserDeserializer implements JsonDeserializer<User> {
#Override public User deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
...........
}
}
and to create Gson instance:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(User.class, new UserSerializer());
gsonBuilder.registerTypeAdapter(User.class, new UserDeserializer());
Gson gson = gsonBuilder.create();
Example
Edit: this is an example of a custom deserializer which might fit into your need. We don't need a custom serializer in this case.
Add this UserDeserializer.java:
public class UserDeserializer implements JsonDeserializer<User> {
#Override
public User deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject obj = json.getAsJsonObject();
User user = new User(obj.get("userId").getAsString(), obj.get("pwd").getAsString(), obj.get("country").getAsString());
return user;
}
}
Replace your fromJson implementation with this (I use generic to avoid the need for casting when calling fromJson):
public static <T> T fromJson(String json, Class<T> clz) {
gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(User.class, new UserDeserializer());
gson = gsonBuilder.create();
return gson.fromJson(json, clz);
}
The only way I can think of would be to have a custom Adapter or deser to a JsonObject and then map it to your User.
With Genson you can create two instances of Genson, one for deserialization and another one for serializaiton. The one used in deserialization could be configured with renamed properties like that.
// you can also precise that you want to rename only the properties from User class
Genson genson = new GensonBuilder()
.rename("username", "userId")
.rename("password", "pwd")
.create();
User user = genson.deserialize(json, User.class);
My json input looks like:
{ user: "sample-user", date : 1225864800 }
And my DateDeserializer class is:
private class DateDeserializer implements JsonDeserializer<Date>
{
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException
{
System.out.println("Deserializer...");
return new Date(json.getAsJsonPrimitive().getAsLong());
}
}
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Date.class, new DateDeserializer());
gson.fromJson(new FileReader("input.json"), MyType.class);
Even after setting up everything, I'm getting
java.text.ParseException: Unparseable Date: "1225864800"
Am I doing anything wrong here? Please help.
You're trying to deserialize the entire Json structure as a Date, not just the date field. You'd need something like:
User user = jsonElement.getAsJsonObject().get( "user" ).getAsString();
Date date = new Date(jsonElement.getAsJsonObject().get( "date" ).getAsLong());
You could write an adapter for the whole MyType class so that you can keep standard date deserialization on other places (if any), and limit your specific deserialization only inside MyType.
To explain better what I mean, here's the code you can copy&paste&run:
package stackoverflow.questions.q14197557;
import java.lang.reflect.Type;
import java.util.Date;
import com.google.gson.*;
public class Q14197557 {
public static class MyType {
String user;
Date date;
#Override
public String toString() {
return "MySample [user=" + user + ", date=" + date + "]";
}
}
public static class MySampleDeserializer implements JsonDeserializer<MyType> {
public MyType deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
if (json == null)
return null;
else {
MyType s = new MyType();
s.user = json.getAsJsonObject().get("user").getAsString();
s.date = new Date(json.getAsJsonObject().get("date").getAsLong());
return s;
}
}
}
public static void main(String[] args) {
String json = "{ user: \"sample-user\", date : 1225864800 }";
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(MyType.class, new MySampleDeserializer());
MyType s = gsonBuilder.create().fromJson(json, MyType.class);
System.out.println("My Type: " + s);
}
}