I have a JSON string that I want to deserilizie using Gson - {"Id":3,"Title":"Roskilde","Description":"Famous Danske festival","StartingTime":"2016-06-12T00:00:00","Duration":"02:02:00"}
The error I get when I try to deserilize the Duration field:
Unparseable date: "02:02:00"
The deserilizer(my idea was to add two possible formats of date deserialization):
Gson gSon= new GsonBuilder().registerTypeAdapter(Date.class, new DateDeserializer()).create();
private static final String[] DATE_FORMATS = new String[] {
"yyyy-MM-dd'T'HH:mm:ss",
"HH:mm:ss"
};
private class DateDeserializer implements JsonDeserializer<Date> {
#Override
public Date deserialize(JsonElement jsonElement, Type typeOF,
JsonDeserializationContext context) throws JsonParseException {
for (String format : DATE_FORMATS) {
try {
return new SimpleDateFormat(format, Locale.US).parse(jsonElement.getAsString());
} catch (ParseException e) {
}
}
throw new JsonParseException("Unparseable date: \"" + jsonElement.getAsString()
+ "\". Supported formats: " + Arrays.toString(DATE_FORMATS));
}
}
and my Event Class(as you can see "Duration" is not of a type date - it's of the type Time - what should I do to make the deserilizer read Duration as type time not date?
private int Id;
private String Title;
private String Description;
private Date StartingTime;
private Time Duration;
public Event(int id, String title,String description, String place, Date startingTime, Time duration)
{
this.Id = id;
this.Description = description;
this.Title = title;
this.StartingTime = startingTime;
this.Duration = duration;
}
Add another class for Time deserialization - make sure you convert the return value to "Time".
(Also see: cast a String to sql time)
private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";
private static final String TIME_FORMAT = "HH:mm:ss";
private class DateDeserializer implements JsonDeserializer<Date> {
#Override
public Date deserialize(JsonElement jsonElement, Type typeOF,
JsonDeserializationContext context) throws JsonParseException {
try {
return new SimpleDateFormat(DATE_FORMAT, Locale.US).parse(jsonElement.getAsString());
} catch (ParseException e) {
}
throw new JsonParseException("Unparseable date: \"" + jsonElement.getAsString()
+ "\". Supported formats: " + DATE_FORMAT);
}
}
private class TimeDeserializer implements JsonDeserializer<Time> {
#Override
public Time deserialize(JsonElement jsonElement, Type typeOF,
JsonDeserializationContext context) throws JsonParseException {
try {
String s = jsonElement.getAsString();
SimpleDateFormat sdf = new SimpleDateFormat(TIME_FORMAT, Locale.US);
sdf.parse(s);
long ms = sdf.parse(s).getTime();
Time t = new Time(ms);
return t;
} catch (ParseException e) {
}
throw new JsonParseException("Unparseable time: \"" + jsonElement.getAsString()
+ "\". Supported formats: " + TIME_FORMAT);
}
}
Register both classes:
GsonBuilder gSonBuilder= new GsonBuilder();
gSonBuilder.registerTypeAdapter(Date.class, new DateDeserializer());
gSonBuilder.registerTypeAdapter(Time.class, new TimeDeserializer());
Gson gSon = gSonBuilder.create();
You should register a deserializer for both Date and Time. Something like this:
try{
// Convert JSON-string to a List of Event objects
Type listType = new TypeToken<ArrayList<Event>>(){}.getType();
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
#Override
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
try{
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH);
return df.parse(json.getAsString());
}
catch(ParseException ex){
return null;
}
});
gsonBuilder.RegisterTypeAdapter(Time.class, new JsonDeserializer<Time>(){
#Override
public Time deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
try{
DateFormat df = new SimpleDateFormat("HH:mm:ss", Locale.ENGLISH);
return df.parse(json.getAsString());
}
catch(ParseException ex){}
}
return null;
}
});
Gson eventGson = gsonBuilder.create();
events = dateGson.fromJson(json, listType);
}
catch(JsonParseException ex){
ex.printStackTrace();
}
PS: This code is untested, since I didn't had a lot of time. But I think you get the general idea. You just need two JsonDeserializers, one for time and one for Date.
Related
I'm using GSON to convert JSONArray to Java objects. I need to convert both long date and simple date format "yyyy-MM-dd'T'HH:mm'Z'" to Java objects. I'm able to convert alone long or simple date but couldn't able to convert both together.
used below code snippet for long conversion :
GsonBuilder builder = new GsonBuilder();
// Register an adapter to manage the date types as long values
builder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
return new Date(json.getAsJsonPrimitive()
.getAsLong());
}
});
Gson gson = builder.create();
Type userListType = new TypeToken<ArrayList<CurrentLocation>>() {
}.getType();
gson.fromJson(data, userListType);
Sample data I need to convert :
[
{
"instance": {
"location": {
"lat": 31.522291,
"lon": -96.532816,
"timestamp": 1587693720000
},
"timeAtLocation": "2020-04-23T04:59Z"
}
},
{
"instance": {
"location": {
"lat": 31.522291,
"lon": -96.532816,
"timestamp": 1737693720000
},
"timeAtLocation": "2020-0-23T04:59Z"
}
}
]
Please try following code:
public class Main {
static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm'Z'";
static final Calendar calendar = Calendar.getInstance();
static class LongUtil {
static boolean isLong(String longValue) {
try {
Long.parseLong(longValue);
return true;
} catch (RuntimeException e) {
return false;
}
}
}
static class DateDeserializer implements JsonDeserializer<Date> {
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_FORMAT);
#Override
public Date deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
System.out.println(type.getTypeName());
System.out.println(jsonElement.getAsJsonPrimitive());
if (jsonElement.getAsJsonPrimitive() != null) {
final String expectedDateValue = jsonElement.getAsJsonPrimitive().getAsString();
if (LongUtil.isLong(expectedDateValue)) {
System.out.println("It is long value hence parsing it to long");
calendar.setTimeInMillis(Long.parseLong(expectedDateValue));
return calendar.getTime();
} else {
System.out.println("It is dateformat value hence parsing it to dateformat");
try {
return simpleDateFormat.parse(expectedDateValue);
} catch (ParseException e) {
throw new JsonParseException("Invalud dateFormat while parsing");
}
}
} else {
throw new JsonParseException("JSOn Premitive Exception null");
}
}
}
public static void main(String[] args) throws IOException {
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Date.class, new DateDeserializer());
Gson gson = builder.create();
Type userListType = new TypeToken<ArrayList<Wrapper>>() {
}.getType();
File file = new File("response.json");
System.out.println("file exists : " + file.exists());
JsonReader jsonReader = new JsonReader(new FileReader(file));
List<Wrapper> wrapper = gson.fromJson(jsonReader, userListType);
System.out.println(wrapper);
}
class Wrapper {
User instance;
#Override
public String toString() {
return "Wrapper{" +
"instance=" + instance +
'}';
}
}
class User {
Location location;
Date timeAtLocation;
#Override
public String toString() {
return "User{" +
"location=" + location +
", timeAtLocation='" + timeAtLocation + '\'' +
'}';
}
}
class Location {
String lat;
String lon;
Date timestamp;
#Override
public String toString() {
return "Location{" +
"lat='" + lat + '\'' +
", lon='" + lon + '\'' +
", timestamp='" + timestamp + '\'' +
'}';
}
}
}
Explaination:
While deserializing i am checking if the input string is either in dateformat or in long and based on that I create the calendar instance, then i set long and finally get date object date otherwise just use the string and format it based on date formatter.
Output:
file exists : true
It is long value hence parsing it to long
It is dateformat value hence parsing it to dateformat
It is long value hence parsing it to long
It is dateformat value hence parsing it to dateformat
[Wrapper{instance=User{location=Location{lat='31.522291', lon='-96.532816', timestamp='Fri May 01 13:49:08 IST 2020'}, timeAtLocation='Thu Apr 23 04:59:00 IST 2020'}}, Wrapper{instance=User{location=Location{lat='31.522291', lon='-96.532816', timestamp='Fri Jan 24 10:12:00 IST 2025'}, timeAtLocation='Mon Dec 23 04:59:00 IST 2019'}}]
I get following exception.
Caused by: java.lang.ClassCastException: Cannot cast java.util.LinkedList to com.example.weltliste.Task
at this line: tasks.add(g.fromJson(in, Task.class));
Here is the full method + my custom deserializer
public class FileHandler {
private DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");
Gson g = new GsonBuilder().setPrettyPrinting()
.registerTypeAdapter(Task.class, new TaskSerializer())
.registerTypeAdapter(Task.class, new TaskDeserializer()).create();
public List<Task> read(InputStream stream) throws IOException {
InputStreamReader in = new InputStreamReader(stream);
List<Task> tasks = null;
tasks.add(g.fromJson(in, Task.class));
return tasks;
}
Here is my custom deserializer
public class TaskDeserializer implements JsonDeserializer<List<Task>> {
#Override
public List<Task> deserialize(JsonElement json,
Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
List<Task> tasks = new LinkedList<>();
JsonArray jsonArray = json.getAsJsonArray();
for (int i = 0; i < jsonArray.size(); i++) {
JsonObject jsonObject;
jsonObject = jsonArray.get(i).getAsJsonObject();
String title = jsonObject.get("title").getAsString();
String value = jsonObject.get("value").getAsString();
LocalDateTime date = LocalDateTime.parse(jsonObject.get("date").getAsString());
boolean checked = jsonObject.get("checked").getAsBoolean();
tasks.add(new Task(title, value, date, checked));
}
return tasks;
}
}
I m trying to parse a JSON file and store it in an list. I m getting this error :
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token
Here is my JSON file
{ "budgetList":[
{
"label":"Salary Tim",
"category":"Monthly Income",
"real":1590,
"estimated":1590,
"date":"",
"month":"",
"year":"",
"type":"Income"
},
{
"label":"Salary Tom",
"category":"Monthly Income",
"real":1540,
"estimated":1540,
"date":"",
"month":"",
"year":"",
"type":"Income"
}
]
}
Here is my code
Budget :
public class Budget {
private String label;
private String category;
private int real;
private int estimated;
private Date date;
private int year;
private String type;
....
....
}
My service :
List<Budget> budgets = objectMapper.readValue(new File("src/main/resources/json/new_exercise.json"), TypeFactory.defaultInstance().constructCollectionType(List.class,
Budget.class));
Where am I wrong?
Thanks in advance.
ANSWER FOUND
Code is
ObjectMapper objectMapper = new ObjectMapper();
List<Budget> budgets = null;
JsonNode node = objectMapper.readTree(new File("src/main/resources/json/new_exercise.json"));
node = node.get("budgetList");
TypeReference<List<Budget>> typeRef = new TypeReference<List<Budget>>(){};
budgets = objectMapper.readValue(node.traverse(), typeRef);
can you, use GSON library? Is very simple
Reader reader = new InputStreamReader(new
FileInputStream("/opt/file.json"));
Gson gson = gsonBuilder.create();
List listBudget = gson.fromJson(reader, new
TypeToken>() {}.getType());
I think that the only problem is when Date and integer parser when is empty. but you can register adapters like:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
public Date deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context)
throws JsonParseException {
try {
return df.parse(json.getAsString());
} catch (ParseException e) {
return null;
}
}
});
Reader reader = new InputStreamReader(new
FileInputStream("/opt/file.json"));
Gson gson = gsonBuilder.create();
List listBudget = gson.fromJson(reader, new
TypeToken>() {}.getType());
It works for you?, and dont forget to validate you json. "
JAva
I have the following problem.
I have a mobile object.
Calss object mobile
private ObjectId _id;
private String number;
private String nroMatricula;
Get and Set, etc.
When recovery of MongoDB.
String id = "5089e5fde4b07bf6f368366b";
DBObject soid = new BasicDBObject("_id", new ObjectId(id));
String s = MongoAccess.getSingleton().GetOneValueByKey("mobile", soid);
Mobile m = js.fromJson(s, Mobile.class);
public String GetOneValueByKey(String thecollection, DBObject key)
{
String result = null;
try {
DBCollection collection = MDB.getCollection(thecollection);
result = JSON.serialize(collection.findOne(key));
} catch (Exception e) {
Logger.getLogger(MongoAccess.class.getName()).log(Level.SEVERE, e.toString());
}
return result;
}
Recovery data correctly but the _id attribute.
I load the data I have in the database, but it generates a new id.
That should be the correct _id "5089e5fde4b07bf6f368366b" but that is not the charge on the object.
I can help.
Solution
JsonDeserializer<ObjectId> des = new JsonDeserializer<ObjectId>() {
#Override
public ObjectId deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) throws JsonParseException {
return new ObjectId(je.getAsJsonObject().get("$oid").getAsString());
}
};
Gson gson = new GsonBuilder().registerTypeAdapter(ObjectId.class, des).create();
I have a JSON response which contains a timestamp, but I'm having some issues parsing it to a date object. I'm having the same difficulty serializing it back into the same format as well. I'm using Gson to decode the JSON responses to objects and this is the only spot I'm having a hicup with.
"TimeStamp":"\/Date(1327650052632+0000)\/"
I did have a look at the custom serialize/deserialize adapters, but couldn't make heads or tails from it.
Regards,
EZFrag
I managed to understand the adapters (sort of). Here is the code I used:
private Gson createGson(){
JsonSerializer<Date> ser = new JsonSerializer<Date>() {
#Override
public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext
context) {
return src == null ? null : new JsonPrimitive("\\/Date("+src.getTime()+"+0000)\\/");
}
};
JsonDeserializer<Date> deser = new JsonDeserializer<Date>() {
#Override
public Date deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
String tmpDate = json.getAsString();
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(tmpDate);
boolean found = false;
while (matcher.find() && !found) {
found = true;
tmpDate = matcher.group();
}
return json == null ? null : new Date(Long.parseLong(tmpDate));
}
};
return new GsonBuilder().serializeNulls()
.registerTypeAdapter(Date.class, ser)
.registerTypeAdapter(Date.class, deser).create();
}
JQuery has this method .
formatJSONDate(Date(result.dateFromJSON))
or you may try this regular expression.
function parseJsonDate(jsonDate) {
var offset = new Date().getTimezoneOffset() * 60000;
var parts = /\/Date\((-?\d+)([+-]\d{2})?(\d{2})?.*/.exec(jsonDate);
if (parts[2] == undefined)
parts[2] = 0;
if (parts[3] == undefined)
parts[3] = 0;
return new Date(+parts[1] + offset + parts[2]*3600000 + parts[3]*60000);
};