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...
Related
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);
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;
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;
Here is LocationSearchMetaData.java
public class LocationSearchMetaData {
private int page;
private String tag;
private SearchPreferences prefs;
private PublishMsgSearchLocality locality;
public PublishMsgSearchLocality getLocality() {
return locality;
}
public void setLocality(PublishMsgSearchLocality locality) {
this.locality = locality;
}
public SearchPreferences getPrefs() {
return prefs;
}
public void setPrefs(SearchPreferences prefs) {
this.prefs = prefs;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
}
SearchPreferences.java
public abstract class SearchPreferences {
private String radius;
private boolean useCurrLoc;
public boolean isUseCurrLoc() {
return useCurrLoc;
}
public void setUseCurrLoc(boolean useCurrLoc) {
this.useCurrLoc = useCurrLoc;
}
public String getRadius() {
return radius;
}
public void setRadius(String radius) {
this.radius = radius;
}
}
PublishMsgSearchLocality.java
public class PublishMsgSearchLocality {
private String formatted_address;
private double lat;
private double lon;
public String getFormatted_address() {
return formatted_address;
}
public void setFormatted_address(String formatted_address) {
this.formatted_address = formatted_address;
}
public double getLat() {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
public double getLon() {
return lon;
}
public void setLon(double lon) {
this.lon = lon;
}
}
My controller
#RestController
#CrossOrigin
#RequestMapping("/api/v1.0/search")
public class SearchController {
#Autowired
private SearchService search;
#Autowired
private AppInstances instances;
#RequestMapping(value="tag",method=RequestMethod.POST)
public List<PublishMessageSearchModel> searchByTag(#RequestBody LocationSearchMetaData metaData)
{
return search.search(instances.getEsClient(), metaData.getLocality().getLat(), metaData.getLocality().getLon(), Integer.parseInt(metaData.getPrefs().getRadius()), metaData.getTag(), metaData.getPage());
}
}
My client request is like this
var req = {
method: 'POST',
url: 'http://192.168.1.2:8084/mobapp/api/v1.0/search/tag',
headers: {
'Content-Type': "application/json"
},
data: searchFormService.getTagSearhReqData()
};
$http(req).then(function(d){
console.log("search data :: "+JSON.stringify(d));
}, function(e){
Here is how actual data request
{"prefs":{"radius":"25","useCurrLoc":true},"page":1,"locality":{"formatted_address":"mylocation","lat":11.9313,"lon":60.579999999},"tag":"tag3"}
Error i getting :
HTTP Status 400 : The request sent by the client was syntactically incorrect.
Try to escape quotes: \".
{\"prefs\":{\"radius\":\"25\",\"useCurrLoc\":true},\"page\":1,\"locality\":{\"formatted_address\":\"mylocation\",\"lat\":11.9313,\"lon\":60.579999999},\"tag\":\"tag3\"}
Update:
You defined class SearchPreferences as abstract. You need to remove this modifier and possibly add empty constructors(it may be requred by JSON mapper).
I'm trying to post a simple model using Restful controllers in Spring Boot, but when I'd like my relationship objects it won't work.
I'm using the latest version of Spring
The Controller Method:
#RequestMapping(value= "rest/person/create", method = RequestMethod.POST)
public ResponseEntity<Person> createOrUpdate(#RequestBody Person person){
System.out.println("creating!");
try{
if (person != null){
peopleRepository.save(person);
}
}
catch (Exception e){
e.printStackTrace();
return new ResponseEntity<Person>(HttpStatus.UNAUTHORIZED);
}
return new ResponseEntity<Person>(HttpStatus.OK);
}
The Person class:
#Entity
public class Person {
#Id
#GeneratedValue
private Long id;
#Temporal(TemporalType.DATE)
#DateTimeFormat(pattern = "dd/MM/yyyy")
private Date registryDate;
#Temporal(TemporalType.DATE)
#DateTimeFormat(pattern = "dd/MM/yyyy")
private Date updateDate;
private String firstName;
private String lastName;
#Temporal(TemporalType.DATE)
#DateTimeFormat(pattern = "dd/MM/yyyy")
private Date birthDate;
private String gender;
private String rg;
private String cpf;
private String phone;
private String celPhone;
#ManyToOne
private Address address;
#Column(unique=true)
private String email;
private String observation;
byte situation;
protected Person(){}
public Person(Long id, Date registryDate, Date updateDate,
String firstName, String lastName, Date birthDate, String gender, String rg,
String cpf, String phone, Address address, String email,
String observation, byte situation) {
super();
this.id = id;
this.registryDate = registryDate;
this.updateDate = updateDate;
this.firstName = firstName;
this.lastName = lastName;
this.birthDate = birthDate;
this.gender = gender;
this.rg = rg;
this.cpf = cpf;
this.phone = phone;
if (address != null)
this.address = address;
this.email = email;
this.observation = observation;
this.situation = situation;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Date getRegistryDate() {
return registryDate;
}
public void setRegistryDate(Date registryDate) {
this.registryDate = registryDate;
}
public Date getUpdateDate() {
return updateDate;
}
public void setUpdateDate(Date updateDate) {
this.updateDate = updateDate;
}
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getRg() {
return rg;
}
public void setRg(String rg) {
this.rg = rg;
}
public String getCpf() {
return cpf;
}
public void setCpf(String cpf) {
this.cpf = cpf;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getObservation() {
return observation;
}
public void setObservation(String observation) {
this.observation = observation;
}
public byte getSituation() {
return situation;
}
public void setSituation(byte situation) {
this.situation = situation;
}
public String getCelPhone() {
return celPhone;
}
public void setCelPhone(String celPhone) {
this.celPhone = celPhone;
}
}
The JSON Object:
var person = {"firstName":"Joao","lastName":"Silva",
"gender":"Masculino","rg":"808080",
"cpf":"00","phone":"0","celPhone":"0",
"address":{"street":"Rua","number":5,"neighborhood":"Bairro",
"city":{"name":"Cidade",
"state":{"name":"Rio Grande do Sul","uf":"RS"},
"uf":"AE"},"cep":"Cep","complement":"Complemento"},
"email":"maluco#gmail.com","observation":"poisé","situation":0};
And the Angular.JS post ->
$http.post('rest/person/create', person).
success(function(data, status, headers, config) {
console.log('all good!');
$scope.create = true;
}).
error(function(data, status, headers, config) {
console.log('error');
$scope.create = false;
});
I've been looking how to do it, and could'nt find it.
I'm completely beginner with Spring
The error happens only with the relationships, if I remove
"address":{"street":"Rua","number":5,"neighborhood":"Bairro",
"city":{"name":"Cidade",
"state":{"name":"Rio Grande do Sul","uf":"RS"},
"uf":"AE"},"cep":"Cep","complement":"Complemento"}
It will work.
You need to declare Content-Type when you post a request, and then #RequesetBody annotation convert http body text to a JSON object using jackson.
So you need to change your content-types, and stringify your json object.
$http({
url: 'rest/person/create',
dataType: 'json',
method: 'POST',
data: JSON.stringify(persion),
headers: {
"Content-Type": "application/json"
}
}).success(function(response){
$scope.response = response;
}).error(function(error){
$scope.error = error;
});