Gson I can't deserialize an array which contains latitude and longitude - arrays

I'm deserializing Json from an air quality site that has an array with latitude and longitude. The Json looks like this:
{
"geo": [
-36.05035,
146.942
],
"name": "Albury South-west Slopes, Australia",
"url": "https://aqicn.org/city/australia/nsw/albury/south-west-slopes"
}
I have written a custom deserializer which does the job but I can't deserialize "geo": [-36.05035, 146.942].
My code looks like this:
public static class City {
private Geo[] geo;
private String name;
private String url;
public Geo[] getGeo() {
return geo;
}
public void setGeo(Geo[] geo) {
this.geo = geo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
public static class Geo {
//what are the getters and setters for an array with no names just numbers?
}
It has me stumped
Thanks Phil

You can use Jackson with custom deserializer. For reference, you can look at Custom deserializer

Let geo be a List<Double> instead of a nested class:
public static class City {
private List<Double> geo;
private String name;
private String url;
public List<Double> getGeo() {
return geo;
}
public void setGeo(List<Double> geo) {
this.geo = geo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
Deserialization should then be straightforward:
String json = "{\"geo\":[-36.05035,146.942],\"name\": \"Albury South-west Slopes, Australia\",\"url\": \"https://aqicn.org/city/australia/nsw/albury/south-west-slopes\"}";
City city = new Gson().fromJson(json, City.class);

Related

Spring MVC + AngularJs: JSON/Model values set to null

I am trying submit json data to a Spring MVC controller mapped with a model. Instead of getting the json values, the values of the fields of the model are all NULL.
IDE debugger:
Chrome:
Exception:
org.springframework.dao.InvalidDataAccessApiUsageException: The given id must not be null!; nested exception is java.lang.IllegalArgumentException: The given id must not be null!
Controller:
#RequestMapping(value = "/update", method = RequestMethod.POST)
#ResponseBody
public PostResponse update(Setting setting, BindingResult bindingResult) {
return settingService.processUpdate(setting, bindingResult, messageSource);
}
JSON data:
{
"updatedAt":1460600207000,
"id":1,
"createdBy":null,
"description":"This is a setting",
"code":"MY_SETTING",
"value":"{\"id\":\"1018\",\"title\":\"Another setting\",\"code\":\"220-203-10-101\"}"
}
Model:
#Entity
#JsonIgnoreProperties(ignoreUnknown = true)
public class Setting {
#Id
#GeneratedValue
#Column
private Integer id;
#Column(unique = true)
private String code;
#Column
private String description;
#Column
private String value;
#Temporal(TemporalType.TIMESTAMP)
#Column(nullable = false)
private Date createdAt;
#Temporal(TemporalType.TIMESTAMP)
#Column(nullable = false)
private Date updatedAt;
#NotFound(action = NotFoundAction.IGNORE)
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="FK_createdByUserId")
private User createdBy;
public Setting() {}
public Setting(String code, String description, String value, Date createdAt, Date updatedAt, User createdBy) {
this.code = code;
this.description = description;
this.value = value;
this.createdAt = createdAt;
this.updatedAt = updatedAt;
this.createdBy = createdBy;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public User getCreatedBy() {
return createdBy;
}
public void setCreatedBy(User createdBy) {
this.createdBy = createdBy;
}
I guess that the setting bean is not mapped at all.
You need to tell spring how to map the http request to the method arguments. If you're posting data, the best way is to add #RequestBody annotation to the relevant method argument (setting in your case)
Modify your controller method like this:
#RequestMapping(value = "/update", method = RequestMethod.POST)
#ResponseBody
public PostResponse update(#RequestBody Setting setting, BindingResult bindingResult) {
return settingService.processUpdate(setting, bindingResult, messageSource);
}

Parse JSON array with resttemplate

I think I have a very common problem but I cant find a solution :(
I am using spring with restTemplate to recover a JSON object like this:
ResponseEntity<Download_urls> result= restTemplate.exchange(URL, HttpMethod.GET, entity, Download_urls.class);
Where "Download_urls " class have a JSON array inside:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
#JsonIgnoreProperties(ignoreUnknown = true)
public class Download_urls {
private Video[] video;
}
And Video.class
#JsonIgnoreProperties(ignoreUnknown = true)
public class Video {
private String type;
private String label;
private String file;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getFile() {
return file;
}
public void setFile(String file) {
this.file = file;
}
}
Obviously Video[] doesn't work to map JSON array. Any help?
Thanks
UPDATE:
Example JSON payload:
{
"id": 737132,
"asset": {
"_class": "asset",
"id": 538362,
"download_urls": {
"Video": [{
"type": "video/mp4",
"label": "360"
}, {
"type": "video/mp4",
"label": "720"
}]
}
}
}
Your Java class names and its properties should follow Java naming conventions. Then your code is much more readable and nicer. And to convert JSON field names to and fro you can use naming strategies, e.g.: LowerCaseWithUnderscoresStrategy, PascalCaseStrategy, etc.
Here you are how I thing classes should look like:
Video.java - same as yours.
DownloadUrls.java:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.PropertyNamingStrategy.PascalCaseStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
#JsonIgnoreProperties(ignoreUnknown = true)
// PascalCaseStrategy is used here because of "Video" JSON field. I would expect
// it to be called "video".
#JsonNaming(PascalCaseStrategy.class)
public class DownloadUrls {
private Video[] video;
public Video[] getVideo() {
return video;
}
public void setVideo(Video[] video) {
this.video = video;
}
}
Asset.java:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
#JsonIgnoreProperties(ignoreUnknown = true)
// LowerCaseWithUnderscoresStrategy is common strategy when used with JSON, but
// in this case it is used because of "download_url" JSON field only.
#JsonNaming(LowerCaseWithUnderscoresStrategy.class)
public class Asset {
int id;
DownloadUrls downloadUrls;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public DownloadUrls getDownloadUrls() {
return downloadUrls;
}
public void setDownloadUrls(DownloadUrls downloadUrls) {
this.downloadUrls = downloadUrls;
}
}
and outer type just for completeness sake:
public class OuterType {
int id;
Asset asset;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Asset getAsset() {
return asset;
}
public void setAsset(Asset asset) {
this.asset = asset;
}
}
Michal
Solved!!
It was my:
private Video[] video;
tried with public attribute and it works:
public Video[] video;

How to convert bootstrap datetimepicker string to java datetime

angular controller
$http({
method: 'POST',
url: '/Eatery/save',
contentType:'application/json',
dataType:'json',
data:resvnCtrl.user
})
Spring mvc controller
#RequestMapping(value="/save",method=RequestMethod.POST,consumes=MediaType.APPLICATION_JSON_VALUE,produces=MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public int save(#RequestBody Reservation reservation) {
System.out.println(reservation.getTime());
return reservationRepo.save(reservation);
}
Java model
#Entity
#Table(name="reservations")
public class Reservation implements Serializable{
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String cnf;
private String name;
private String email;
private String phone;
#JsonDeserialize(using=CustomJsonDateDeserializer.class)
private LocalDateTime time;
private int seats;
private String note;
public Reservation() { }
public Reservation(String cnf, String name, String email, String phone,
LocalDateTime time, int seats, String note) {
this.cnf = cnf;
this.name = name;
this.email = email;
this.phone = phone;
this.time = time;
this.seats = seats;
this.note = note;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCnf() {
return cnf;
}
public void setCnf(String cnf) {
this.cnf = cnf;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public LocalDateTime getTime() {
return time;
}
public void setTime(LocalDateTime time) {
this.time = time;
}
public int getSeats() {
return seats;
}
public void setSeats(int seats) {
this.seats = seats;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
}
From browser console
email: "kerhb#regerg.e"
name: "kjergk"
note: "wefwef"
phone: "1234567899"
seats: 2
time: "10/23/2015 5:53 PM"
Custom date deserializer
public class CustomJsonDateDeserializer extends JsonDeserializer<Date>
{
#Override
public Date deserialize(JsonParser jsonparser,
DeserializationContext deserializationcontext) throws IOException, JsonProcessingException {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String date = jsonparser.getText();
try {
return format.parse(date);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
I have a bootstrap datetimepicker on UI and a java REST webservice at the backend. when i send date select, i got "The request sent by the client was syntactically incorrect.". the datetime string which is sent did not map to the java model. can someone spot my error
#Marged is rigth saying that you didn't cover AM/PM in your date pattern. The proper patter would be yyyy-MM-dd HH:mm a. Note also that you don't need a custom deserializer for this, can rather use #DateTimeFormat
#DateTimeFormat(pattern = "yyyy-MM-dd HH:mm a")
private LocalDateTime time;

Passing parameters using the PUT method

I defined an endpoint with the following methods:
#ApiMethod(name = "update", path = "properties/{id}", httpMethod = HttpMethod.PUT)
public void update(#Named("id") Long id, RealEstatePropertyAPI propertyAPI,
User user) {
On the client side I tried several calls but none of them populates the propertyAPI object on the server side. The instance is created with all fields set to null except the id.
var jsonId = { 'id': '11'};
var x = {"name": "Test","address": { "street": "White House"}};
gapi.client.realestate.update(jsonId, x).execute(function(resp) {
console.log('PropertyEdited');
console.log(resp);
});
Or
var jsonId = { 'id': '11'};
var x = {"name": "Test","address": { "street": "White House"}};
gapi.client.realestate.update(jsonId, {'resource' : x}).execute(function(resp) {
console.log('PropertyEdited');
console.log(resp);
});
The Java classes:
public class RealEstatePropertyAPI {
private Long id;
private String name;
private AddressAPI address;
public RealEstatePropertyAPI() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public AddressAPI getAddress() {
return address;
}
public void setAddress(AddressAPI address) {
this.address = address;
}
}
public class AddressAPI {
private Long id;
private String street;
private String city;
private String state;
private String zip;
private String country;
public AddressAPI() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getZip() {
return zip;
}
public void setZip(String zip) {
this.zip = zip;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}
I'm not actually sure about about this, but you can try to pass all the parameters within a single object, I mean wrap the parameters with brackets { }, like this:
//var jsonId = { 'id': '11'};
var x = {"name": "Test","address": { "street": "White House"}};
gapi.client.realestate.update({'id': '11', 'resource' : x}).execute(function(resp) {
console.log('PropertyEdited');
console.log(resp);
});
Because in fact in both your requests you're sending 2 objects... And I think you have to use 'resource' for the parameters in the POST data as in your second option...

JAVA Google App Engine + Facebook API + GSON = Trouble with Javabean

I am trying to get the user's friends list from Facebook.
The problem seems to be the Javabean...
FBUser fbuser = new Gson().fromJson(jsonStr, FBUser.class);
public class FBUser implements Serializable {
private static final long serialVersionUID = -3154429420153433117L;
private String id;
private String name;
private String email;
private Friends friendsList = new Friends();
private FBUser() { }
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public List<Data> getFriendsList() {
return friendsList.getData();
}
public static class Friends implements Serializable {
private static final long serialVersionUID = 6991758772193514527L;
private List<Data> data;
private Friends() { }
public List<Data> getData() {
return data;
}
public void setData(List<Data> data) {
this.data = data;
}
public class Paging implements Serializable {
private static final long serialVersionUID = 1689816298710621080L;
private String next;
private Paging() { }
public String getNext() {
return next;
}
public void setNext(String next) {
this.next = next;
}
}
}
public class Data implements Serializable {
private static final long serialVersionUID = -5008541658519841090L;
private String id;
private String name;
private Data() { }
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
Json:
json: {"id":"10861234","name":"Whatever","email":"whatever\u0040gmail.com","friends":{"data":[{"name":"Someone","id":"10861234"},{"name" ...43"}],"paging":{"next":"https:\/\/graph.facebook.com\/10861234\/friends..."}}}
The fields ID, Name and Email I can retrieve succesfully... but the friendsList is null... =(
Maybe it is the way I am trying to get it from the nested class, any suggestions on that?
There is no friendsList in your JSON (or, there's no friends in your Java class - whichever way you'd like to look at it). Gson silently ignores anything in the JSON that is not present in your classes.
You have a field friends whose value is an object. That object has a field data which is an array of objects and a field paging which is another object.
You need to write Java classes that match that structure. You're ... close.
In your FBUser class change:
private Friends friendsList = new Friends();
to:
private Friends friends = new Friends();
or:
#SerializedName("friends")
private Friends friendsList = new Friends();
Then in your Friends class you need to add:
private Paging paging = new Paging();
Also note that you don't have to initialize these values unless you specifically don't want them to be non-null when using these classes elsewhere.

Resources