I have a JSON with Joda DateTime field. It has some sample values. But whenever I convert it to Object it automatically takes the current DateTime instead of the DateTime present in the JSON.
PFB the sample JSON
[{
"pas": "CSP",
"policyNumber": "ZU131874",
"schemeName": "PepsiCo employee scheme20",
"policyStatus": "ACTIVE",
"productCode": "GPP",
"totalSavings": 100000,
"investmentReturn": 55000,
"effectiveDate": {
"startDate": {
"dayOfYear": 2,
"year": 2014,
"dayOfMonth": 2,
"dayOfWeek": 4,
"era": 1,
"weekOfWeekyear": 1,
"millisOfSecond": 0,
"secondOfMinute": 0,
"minuteOfDay": 0,
"centuryOfEra": 20,
"yearOfCentury": 14,
"hourOfDay": 0,
"monthOfYear": 1,
"weekyear": 2014,
"minuteOfHour": 0,
"yearOfEra": 2014,
"secondOfDay": 0,
"millisOfDay": 0,
"millis": 1388601000000
},
"endDate": null
}
}, {
"pas": "CSP",
"policyNumber": "ZU146271",
"schemeName": "PepsiCo employee scheme7",
"policyStatus": "ACTIVE",
"productCode": "GPP",
"totalSavings": 100000,
"investmentReturn": 55000,
"effectiveDate": {
"startDate": {
"dayOfYear": 156,
"year": 2015,
"dayOfMonth": 5,
"dayOfWeek": 5,
"era": 1,
"weekOfWeekyear": 23,
"millisOfSecond": 0,
"secondOfMinute": 0,
"minuteOfDay": 0,
"centuryOfEra": 20,
"yearOfCentury": 15,
"hourOfDay": 0,
"monthOfYear": 6,
"weekyear": 2015,
"minuteOfHour": 0,
"yearOfEra": 2015,
"secondOfDay": 0,
"millisOfDay": 0,
"millis": 1433442600000
},
"endDate": null
}
}]
I am using following code to convert list of JSON objects to a list Of Java objects.
policies = new ArrayList<Policy>();
JsonParser parser = new JsonParser();
JsonElement jsonElement = parser.parse(new FileReader("./src/test/resources/" + "sample-zurich-pensions.json"));
Type listType = new TypeToken<List<Policy>>(){}.getType();
List<Policy> policyList = new Gson().fromJson(jsonElement, listType);
policies.addAll(policyList);
In the jsonElement I am getting the exact value, but in the policyList the DateTime is set to the current date.
PFB the classes
Policy.java
private String pas;
private String policyNumber;
private String schemeName;
private String policyStatus;
private String productCode;
private BigDecimal totalSavings;
private BigDecimal investmentReturn;
private EffectiveDate effectiveDate;
EffectiveDate.java
private DateTime startDate;
private DateTime endDate;
During deserialization from JSON, Gson is creating a new DateTime() (which is equal to current system DateTime). The fields present in your JSON are based on getters in DateTime, but there are no setters for them present, so the object cannot be adjusted to the timestamp represented by the JSON. You are much better off using a standard date-time representation like ISO 8601. Then, implement a JsonSerializer and JsonDeserializer for DateTime as suggested on the Gson site:
class DateTimeTypeConverter implements JsonSerializer<DateTime>, JsonDeserializer<DateTime> {
#Override
public JsonElement serialize(DateTime src, Type srcType, JsonSerializationContext context) {
return new JsonPrimitive(src.toString());
}
#Override
public DateTime deserialize(JsonElement json, Type type, JsonDeserializationContext context)
throws JsonParseException {
return new DateTime(json.getAsString());
}
}
or use one of the solutions provided in this post (linked also by #user2762451). You can register the serializer/deserializer like this:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(DateTime.class, new DateTimeTypeConverter());
Gson gson = gsonBuilder.create();
Related
This question already has answers here:
Jackson SerializationFeature.WRITE_DATES_AS_TIMESTAMPS not turning off timestamps in spring
(5 answers)
Closed 1 year ago.
I am converting java object into json object. But OffsetDatetime also being converted to json format. Is it possible to keep the time object as OffsetDatetime timestamp itself.
Java object
{
"start_date": "2022-01-01T13:45:00+01:00",
"origin": {
"type": "AIRPORT",
"search_display_name": "Malmo, Sweden (MMX-Sturup)",
"search_string": "MMX",
"city": "Malmo"
}
}
After converting to json, getting as follows
{
"start_date": {
"offset": {
"total_seconds": 0,
"id": "Z",
"rules": {
"fixed_offset": true,
"transition_rules": [
],
"transitions": [
]
}
},
"day_of_month": 1,
"day_of_week": "SATURDAY",
"day_of_year": 1,
"month": "JANUARY",
"month_value": 1,
"year": 2022,
"hour": 12,
"minute": 45,
"nano": 0,
"second": 0
},
"origin": {
"search_display_name": "Malmo, Sweden (MMX-Sturup)",
"search_string": "MMX",
"city": "Malmo"
}
}
Is it possible to keep offsetDateTime like this "2022-01-01T13:45:00+01:00"
Java object will be converted to json using this method objectMapper.valueToTree(response)
Object mapper configuration as follows
#Bean("objectMapperJavaTime")
public ObjectMapper objectMapperJavaTime() {
return JacksonObjectMapperFactory.createMapperWithDefaultConfigurations()
.registerModule(new JavaTimeModule())
.enable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
}
public class JacksonObjectMapperFactory {
public static ObjectMapper createMapperWithDefaultConfigurations(){
return new Jackson2ObjectMapperBuilder()
.featuresToDisable(WRITE_DATES_AS_TIMESTAMPS)
.failOnUnknownProperties(false)
.serializationInclusion(NON_NULL)
.propertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)
.modules(new JodaModule())
.build();
}
}
Often there are issues attempting to disable the WRITE_DATES_AS_TIMESTAMPS feature on creation like that.
So the solution is not to apply the featrue on creation, so remove this:
.featuresToDisable(WRITE_DATES_AS_TIMESTAMPS)....
And instead of setting feature and returning the objectMapper on one line, you can break it up and set the feature to false after the ObjectMapper has been created:
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);`
Then return the objectMapper.
I have the following jsonObject:
"dateCreated": {
"year": 2021,
"dayOfYear": 145,
"equalNow": false,
"weekyear": 2021,
"chronology": {
"zone": {
"ID": "UTC"
}
},
"weekOfWeekyear": 21,
"secondOfMinute": 10,
"millisOfDay": 10990000,
"monthOfYear": 5,
"dayOfWeek": 2,
"beforeNow": true,
"minuteOfDay": 183,
"dayOfMonth": 25,
"era": 1,
"zone": {
"ID": "UTC"
},
"yearOfCentury": 21,
"centuryOfEra": 20,
"hourOfDay": 3,
"secondOfDay": 10990,
"millis": 1621911790000,
"yearOfEra": 2021,
"minuteOfHour": 3,
"millisOfSecond": 0,
"afterNow": false
}
I need to convert it for this format:
2021-05-25T03:03:10.000Z
Since I don't have a pojo for that object, it's coming from a jsonArray, I'm struggling to get a Datetime from it.
I tried ObjectMapper, JSON(GSON) and still no success.
Does anyone have a clue how can I do it?
edit.: It's a list of Recordings that I converted to JsonArray (to manipulate, adding another field into the json). When I convert the list to jsonArray, that field (type DateTime) becomes serialized and I need it back to the correct format to pass it forward.
Recording.class;
private final DateTime dateCreated;
List<Recording> listRecordings;
JSONArray jsonArray = new JSONArray(listRecordings);
jsonArray ->
[
{
"offset": 179161383840,
"type": "AUDIO",
"duration": 232,
"codec": "OPUS",
"dateCreated": {
"year": 2021,
"dayOfYear": 145,
"equalNow": false,
"weekyear": 2021,
"chronology": {
"zone": {
"ID": "UTC"
}
},
"weekOfWeekyear": 21,
"secondOfMinute": 10,
"millisOfDay": 10990000,
"monthOfYear": 5,
"dayOfWeek": 2,
"beforeNow": true,
"minuteOfDay": 183,
"dayOfMonth": 25,
"era": 1,
"zone": {
"ID": "UTC"
},
"yearOfCentury": 21,
"centuryOfEra": 20,
"hourOfDay": 3,
"secondOfDay": 10990,
"millis": 1621911790000,
"yearOfEra": 2021,
"minuteOfHour": 3,
"millisOfSecond": 0,
"afterNow": false
},
"size": 521517,
"containerFormat": "MKA",
"status": "COMPLETED"
}
]
I need to revert back dateCreated for the original format: 2021-05-25T03:03:10.000Z
Edit3.:
My workaround:
for (Recording recording : listRecordings) {
Object jsonObject = JSONObject.wrap(recording);
((JSONObject) jsonObject).put("dateCreated", recording.getDateCreated());
jsonArray.put(jsonObject);
}
Best Regards,
The threaded comments are stored in Database as flat records with commenId and ParentCommentId. Like below.
commentId : 1
userId : 815
userFName:Joe
userLName:Doe
timeStamp:12345678888
commentText:""
parentCommentId:0
commentId : 2
userId : 615
userFirstName:Ken
userLastName:Tait
timeStamp:12345678988
commentText:"Comment text"
parentCommentId:1
commentId : 3
userId : 415
userFirstName:Brain
userLastName:Dell
timeStamp:12345678
commentText:"Comment text"
parentCommentId:0
I build the Java object using the following Java class
public class Comment {
int commentId;
int userId;
String userFName;
String userLName;
long timeStamp;
String commentText;
int parCommId;
}
List<Comment> comments;
I have the List of comments object. Now I have to traverse the list and convert this list of comment object into nested Json object. The comment objects with parCommId == 0 are the top level comment and the other comment objects (parCommId != 0) should be nested under the commentId of the comment object.
In the above example, the output should be nested like below
CommentId_1
CommentId_2
CommentID_3
As suggested in the comments, let's add a List<Comment> field in Comment.class.
Then, assuming the input from the DB is:
List<Comment> comments = Arrays.asList(
new Comment(1, 6, "John", "Snow", 0, "asd", 0),
new Comment(2, 6, "Tif", "Snow", 0, "asd2", 1),
new Comment(3, 6, "Yur", "Snow", 0, "asd", 2),
new Comment(4, 6, "Mrr", "Snow", 0, "asd", 0),
new Comment(5, 6, "Mrr", "Snow", 0, "asd", 2)
);
You can do the following:
Map<Integer, List<Comment>> parentToComments = comments.stream()
.collect(Collectors.groupingBy(Comment::getParCommId));
comments.forEach(comment -> {
List<Comment> children = parentToComments.get(comment.getCommentId());
comment.setChildren(children);
});
ObjectMapper objectMapper = new ObjectMapper();
String commentsJson = objectMapper.writeValueAsString(parentToComments.get(0));
Output:
[{
"commentId": 1,
"userId": 6,
"userFName": "John",
"userLName": "Snow",
"timeStamp": 0,
"commentText": "asd",
"parCommId": 0,
"children": [{
"commentId": 2,
"userId": 6,
"userFName": "Tif",
"userLName": "Snow",
"timeStamp": 0,
"commentText": "asd2",
"parCommId": 1,
"children": [{
"commentId": 3,
"userId": 6,
"userFName": "Yur",
"userLName": "Snow",
"timeStamp": 0,
"commentText": "asd",
"parCommId": 2,
"children": null
}, {
"commentId": 5,
"userId": 6,
"userFName": "Mrr",
"userLName": "Snow",
"timeStamp": 0,
"commentText": "asd",
"parCommId": 2,
"children": null
}]
}]
}, {
"commentId": 4,
"userId": 6,
"userFName": "Mrr",
"userLName": "Snow",
"timeStamp": 0,
"commentText": "asd",
"parCommId": 0,
"children": null
}]
This question already has answers here:
How to read json file into java with simple JSON library
(21 answers)
Closed 5 years ago.
I have this string which located inside external file.
{
"IsValid": true,
"LiveSessionDataCollection": [
{
"CreateDate": "2017-12-27T13:29:06.595Z",
"Data": "Khttp://www8.hp.com/us/en/large-format-printers/designjet-printers/products.html&AbSGOX+SGOXpLXpBF8CXpGOA9BFFPconsole.info('DeploymentConfigName%3DRelease_20171227%26Version%3D1')%3B&HoConfig: Release_20171227&AwDz//////8NuaCh63&Win32&SNgYAJBBYWCYKW9a&2&SGOX+SGOXpF/1en-us&AAAAAAAAAAAAQICBCXpGOAAMBBBB8jl",
"DataFlags": 8,
"DataFlagType": 264,
"LegacyLiveSessionDataType": null,
"LiveSessionId": 1545190526042650,
"MessageNumber": 0,
"StreamId": 0,
"StreamMessageId": 0,
"ProjectId": 201
},
{
"CreateDate": "2017-12-27T13:29:08.887Z",
"Data": "oDB Information Level : Detailed&9BbRoDB Annual Sales : 55000000&BoDB Audience : Mid-Market Business&AoDB%20Audience%20Segment%20%3A%20Retail%20%26%20Distribution&AoDB B2C : true&AoDB Company Name : Clicktale Inc&AoDB SID : 120325490&AoDB Employee Count : 275&AoDB Employee Range : Mid-Market&AoDB%20Industry%20%3A%20Retail%20%26%20Distribution&AoDB Revenue Range : $50M - $100M&AoDB Sub Industry : Electronics&AoDB Traffic : High&AWB9tY/8bvOBBP_({\"a\":[{\"a\":{\"s\":\"w:auto;l:auto;\"},\"n\":\"div53\"}]})&sP_({\"a\":[{\"a\":{\"s\":\"w:auto;l:auto;\"},\"n\":\"div62\"}]})&FP_({\"r\":[\"script2\"],\"m\":[{\"n\":{\"nt\":1,\"tn\":\"SCRIPT\",\"a\":{\"async\":\"\",\"src\":\"http://admin.brightcove.com/js/api/SmartPlayerAPI.js?_=1514381348598\"},\"i\":\"script55\"},\"t\":false,\"pn\":\"head1\"}]})&8GuP_({\"a\":[{\"a\":{\"s\":\"t:0px;mt:0px;l:274.5px;ml:0px;\"},\"n\":\"div442\"}]})&SP_({\"a\":[{\"a\":{\"s\":\"t:0px;mt:0px;l:274.5px;ml:0px;\"},\"n\":\"div444\"}]})&D",
"DataFlags": 8,
"DataFlagType": 264,
"LegacyLiveSessionDataType": null,
"LiveSessionId": 1545190526042650,
"MessageNumber": 1,
"StreamId": 0,
"StreamMessageId": 1,
"ProjectId": 201
},
{
"CreateDate": "2017-12-27T13:29:08.971Z",
"Data": "P_({\"a\":[{\"a\":{\"s\":\"mih:480px;\"},\"n\":\"div105\"},{\"a\":{\"s\":\"mih:480px;\"},\"n\":\"div114\"},{\"a\":{\"s\":\"mih:480px;\"},\"n\":\"div123\"}]})&9B+8P_({\"a\":[{\"a\":{\"s\":\"mih:480px;\"},\"n\":\"div167\"},{\"a\":{\"s\":\"mih:480px;\"},\"n\":\"div169\"},{\"a\":{\"s\":\"mih:480px;\"},\"n\":\"div178\"}]})&JP_({\"a\":[{\"a\":{\"s\":\"mih:457px;\"},\"n\":\"div220\"},{\"a\":{\"s\":\"mih:457px;\"},\"n\":\"div229\"},{\"a\":{\"s\":\"mih:457px;\"},\"n\":\"div238\"}]})&FP_({\"a\":[{\"a\":{\"s\":\"mih:480px;\"},\"n\":\"div282\"},{\"a\":{\"s\":\"mih:480px;\"},\"n\":\"div291\"},{\"a\":{\"s\":\"mih:480px;\"},\"n\":\"div300\"}]})&HP_({\"a\":[{\"a\":{\"s\":\"t:0px;mt:-92px;l:274.5px;ml:0px;\"},\"n\":\"div442\"}]})&HP_({\"a\":[{\"a\":{\"s\":\"t:0px;mt:-92px;l:274.5px;ml:0px;\"},\"n\":\"div444\"}]})&B",
"DataFlags": 8,
"DataFlagType": 264,
"LegacyLiveSessionDataType": null,
"LiveSessionId": 1545190526042650,
"MessageNumber": 2,
"StreamId": 0,
"StreamMessageId": 2,
"ProjectId": 201
},
{
"CreateDate": "2017-12-27T13:29:08.98Z",
"Data": "P_({\"r\":[\"object1\",\"param1\",\"param2\",\"param3\",\"param4\",\"param5\",\"param6\",\"param7\",\"param8\",\"param9\",\"param10\",\"param11\",\"param12\",\"param13\",\"param14\",\"param15\"],\"m\":[{\"n\":{\"nt\":1,\"tn\":\"OBJECT\",\"a\":{\"type\":\"application/x-shockwave-flash\",\"i\":\"LNK--1710e8cd-4820-4be0-8cf0-28d57402afd8LNK--1710e8cd-4820-4be0-8cf0-28d57402afd8\",\"width\":\"720\",\"height\":\"422\",\"c\":\"BrightcoveExperience BrightcoveExperienceID_1039\",\"seamlesstabbing\":\"undefined\"},\"i\":\"object3\"},\"t\":false,\"pn\":\"div443\",\"ps\":\"meta29\"},{\"n\":{\"nt\":1,\"tn\":\"SCRIPT\",\"a\":{\"type\":\"text/javascript\",\"src\":\"http://admin.brightcove.com/js/api/SmartPlayerAPI.js\"},\"i\":\"script56\"},\"t\":false,\"pn\":\"div443\",\"ps\":\"object3\"},{\"n\":{\"nt\":1,\"tn\":\"PARAM\",\"a\":{\"name\":\"allowScriptAccess\",\"v\":\"always\"},\"i\":\"param31\"},\"t\":false,\"pn\":\"object3\"},{\"n\":{\"nt\":1,\"tn\":\"PARAM\",\"a\":{\"name\":\"allowFullScreen\",\"v\":\"true\"},\"i\":\"param32\"},\"t\":false,\"pn\":\"object3\",\"ps\":\"param31\"},{\"n\":{\"nt\":1,\"tn\":\"PARAM\",\"a\":{\"name\":\"seamlessTabbing\",\"v\":\"false\"},\"i\":\"param33\"},\"t\":false,\"pn\":\"object3\",\"ps\":\"param32\"},{\"n\":{\"nt\":1,\"tn\":\"PARAM\",\"a\":{\"name\":\"swliveconnect\",\"v\":\"true\"},\"i\":\"param34\"},\"t\":false,\"pn\":\"object3\",\"ps\":\"param33\"},{\"n\":{\"nt\":1,\"tn\":\"PARAM\",\"a\":{\"name\":\"wmode\",\"v\":\"opaque\"},\"i\":\"param35\"},\"t\":false,\"pn\":\"object3\",\"ps\":\"param34\"},{\"n\":{\"nt\":1,\"tn\":\"PARAM\",\"a\":{\"name\":\"quality\",\"v\":\"high\"},\"i\":\"param36\"},\"t\":false,\"pn\":\"object3\",\"ps\":\"param35\"},{\"n\":{\"nt\":1,\"tn\":\"PARAM\",\"a\":{\"name\":\"bgcolor\",\"v\":\"FFFFFF\"},\"i\":\"param37\"},\"t\":false,\"pn\":\"object3\",\"ps\":\"param36\"}]})&9CAQ",
"DataFlags": 8,
"DataFlagType": 264,
"LegacyLiveSessionDataType": null,
"LiveSessionId": 1545190526042650,
"MessageNumber": 3,
"StreamId": 0,
"StreamMessageId": 3,
"ProjectId": 201
},
{
"CreateDate": "2017-12-27T13:29:09.413Z",
"Data": "P_({\"a\":[{\"a\":{\"s\":\"w:720px;h:422px;p:relative;\"},\"n\":\"div443\"},{\"a\":{\"s\":\"p:relative;\"},\"n\":\"div445\"}],\"r\":[\"script55\"],\"m\":[{\"n\":{\"nt\":1,\"tn\":\"DIV\",\"a\":{\"c\":\"spooler\",\"s\":\"d:block;o:0;\"},\"i\":\"div451\"},\"t\":false,\"pn\":\"div443\"},{\"n\":{\"nt\":1,\"tn\":\"DIV\",\"a\":{\"c\":\"ispl_sm\",\"s\":\"o:1;\"},\"i\":\"div452\"},\"t\":false,\"pn\":\"div451\"},{\"n\":{\"nt\":1,\"tn\":\"DIV\",\"a\":{\"c\":\"layer\",\"s\":\"o:1;\"},\"i\":\"div453\"},\"t\":false,\"pn\":\"div451\",\"ps\":\"div452\"},{\"n\":{\"nt\":1,\"tn\":\"DIV\",\"a\":{\"c\":\"spooler\",\"s\":\"d:block;o:0;\"},\"i\":\"div454\"},\"t\":false,\"pn\":\"div445\"},{\"n\":{\"nt\":1,\"tn\":\"DIV\",\"a\":{\"c\":\"ispl_sm\",\"s\":\"o:1;\"},\"i\":\"div455\"},\"t\":false,\"pn\":\"div454\"},{\"n\":{\"nt\":1,\"tn\":\"DIV\",\"a\":{\"c\":\"layer\",\"s\":\"o:1;\"},\"i\":\"div456\"},\"t\":false,\"pn\":\"div454\",\"ps\":\"div455\"}]})&9CA5P_({\"a\":[{\"a\":{\"s\":\"d:block;o:0.0282439;\"},\"n\":\"div451\"},{\"a\":{\"s\":\"o:0.989022;\"},\"n\":\"div453\"},{\"a\":{\"s\":\"d:block;o:0.0282439;\"},\"n\":\"div454\"},{\"a\":{\"s\":\"o:0.989022;\"},\"n\":\"div456\"}]})&W",
"DataFlags": 8,
"DataFlagType": 264,
"LegacyLiveSessionDataType": null,
"LiveSessionId": 1545190526042650,
"MessageNumber": 4,
"StreamId": 0,
"StreamMessageId": 4,
"ProjectId": 201
}
]
I am trying to parse it into JSON array object , when I searched for it in Google I found the following solution:
JSONArray jsonArray = new JSONArray("path_to_file_to_parse");
but when I wrote it inside my code I got an error. Is there another way to make it?
I am using json-simple version 1.1
Have you looked at Jackson Tree Model?
//first, you create a mapper object
ObjectMapper mapper = new ObjectMapper();
//then you create a JsonNode instance representing your JSON root structure
//you will need to define json yourself to run the code.
JsonNode root = null;
try {
root = mapper.readTree(json);
} catch (IOException e) {
System.out.println("Some Error");
}
//here you get the list of your session nodes
JsonNode list = root.path("LiveSessionDataCollection");
//then you can iterate through them and get any inner value
for (JsonNode session : list) {
//for example, you can get the create date or live session id.
System.out.println(session.path("CreateDate"));
System.out.println(session.path("LiveSessionId"));
}
I may not be understanding your question fully but I think this is what you're after.
I am trying to get weather forecast data from the WeatherUnderground API.
So far I am using the following code:
URLConnection connection = url.openConnection();
connection.setConnectTimeout(5000);
connection.connect();
JsonParser jp = new JsonParser();
JsonElement forecastJson = jp.parse(new InputStreamReader((InputStream) connection.getContent())).getAsJsonObject()
.getAsJsonObject().get("forecast")
.getAsJsonObject().get("simpleforecast")
.getAsJsonObject().getAsJsonArray("forecastday").get(1);
System.out.println("forecastJson = " + forecastJson.toString());
String date = String.valueOf(jp.parse(forecastJson
.getAsJsonObject().get("date")
.getAsJsonObject().get("epoch").getAsString()));
String high = String.valueOf(jp.parse(forecastJson
.getAsJsonObject().get("high")
.getAsJsonObject().get("celsius").getAsString()));
String low = String.valueOf(jp.parse(forecastJson
.getAsJsonObject().get("low")
.getAsJsonObject().get("celsius").getAsString()));
String conditions;
try {
conditions = String.valueOf(jp.parse(forecastJson
.getAsJsonObject().get("conditions").getAsString()));
} catch (JsonSyntaxException e) {
e.printStackTrace();
}
The JsonElement forecastJson" I receive looks like this:
{
"date": {
"epoch": "1467046800",
"pretty": "7:00 PM CEST on June 27, 2016",
"day": 27,
"month": 6,
"year": 2016,
"yday": 178,
"hour": 19,
"min": "00",
"sec": 0,
"isdst": "1",
"monthname": "June",
"monthname_short": "Jun",
"weekday_short": "Mon",
"weekday": "Monday",
"ampm": "PM",
"tz_short": "CEST",
"tz_long": "Europe/Berlin"
},
"period": 2,
"high": {
"fahrenheit": "77",
"celsius": "25"
},
"low": {
"fahrenheit": "58",
"celsius": "14"
},
"conditions": "Partly Cloudy",
"icon": "partlycloudy",
"icon_url": "http://icons.wxug.com/i/c/k/partlycloudy.gif",
"skyicon": "",
"pop": 0,
"qpf_allday": {
"in": 0,
"mm": 0
},
"qpf_day": {
"in": 0,
"mm": 0
},
"qpf_night": {
"in": 0,
"mm": 0
},
"snow_allday": {
"in": 0,
"cm": 0
},
"snow_day": {
"in": 0,
"cm": 0
},
"snow_night": {
"in": 0,
"cm": 0
},
"maxwind": {
"mph": 15,
"kph": 24,
"dir": "W",
"degrees": 260
},
"avewind": {
"mph": 11,
"kph": 18,
"dir": "W",
"degrees": 260
},
"avehumidity": 48,
"maxhumidity": 0,
"minhumidity": 0
}
I am able to get the "date", "high" and "low" Strings, but I'm unable to get the "conditions" and I don't understand what I'm doing wrong.
I am getting the following exception:
com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON
As far as I understand the JSON is not malformed. How am I supposed to get the "conditions" value?
I've tried other JSON parsers / libraries as well, but nothing worked out. I'd like to continue working with the Gson-Library, and I guess I'm quite close, but stuck.
Thanks for any help.
If you break down the line that's throwing the exception you can see that you are actually trying to parse as JSON a string that is in fact not JSON.
try {
JsonObject jo = forecastJson.getAsJsonObject();
JsonElement je = jo.get("conditions");
String s1 = je.getAsString();
// at this point s1 contains the value "Partly Cloudy" which you
// are trying to parse as JSON.
JsonElement je2 = jp.parse(s1);
conditions = String.valueOf(je2);
} catch (JsonSyntaxException e) {
e.printStackTrace();
}
As "JB Nizet" pointed out in the comment under my question, I was trying to parse the JSON every time again when I wanted to get another piece of its contents. That was my (beginner) mistake.
Now I parse only once and then get the contents directly, without any problem:
JsonParser jp = new JsonParser();
JsonElement forecastJson = jp.parse(new InputStreamReader((InputStream) connection.getContent())).getAsJsonObject()
.getAsJsonObject().get("forecast")
.getAsJsonObject().get("simpleforecast")
.getAsJsonObject().getAsJsonArray("forecastday").get(1);
String date = forecastJson.getAsJsonObject().get("date")
.getAsJsonObject().get("epoch").getAsString();
String high = forecastJson.getAsJsonObject().get("high")
.getAsJsonObject().get("celsius").getAsString();
String low = forecastJson.getAsJsonObject().get("low")
.getAsJsonObject().get("celsius").getAsString();
String conditions = forecastJson.getAsJsonObject()
.get("conditions").getAsString();
First of all, as they say in the comments there's really no need to parse every piece again.
String date = String.valueOf(jp.parse(forecastJson
.getAsJsonObject().get("date")
.getAsJsonObject().get("epoch").getAsString()));
Is the same as:
String date = forecastJson.getAsJsonObject().get("date")
.getAsJsonObject().get("epoch").getAsString();
The problem that you're experiencing is actually something that I suspect is a bug in the Gson library. When it tries to parse a string with spaces in it, it will tokenize that string and expect that after the first word (Partly in this case) the document should end and that the json is malformed since it hasn't reached the end of the document.
So to solve this, either do as the comments say, which is the reasonable thing in your case. Or if you wan't you could always change Partly cloudy to for example Partly_cloudy and it will work :)