I'm new to Typescript and started using it to play with Ionic. I come from a Java background and I'm experiencing some trouble getting accustomed to it's syntax and way of doing things. Specifically creating new object instances and getting them initialized.
Recently I came across this issue which I cannot explain. I'm sending a HTTP GET request and getting it's response in a Javascript Object.
To work with this response, I'm trying to map this Javascript Object I received to a typescriptclass of mine which I called HttpResponse, creating a new instance of it when I receive the response. To make things easier I created a simple fiddle which ilustrates my problem.
You can find the quick written fiddle on this link
As you can see on the output, object data is there but when I invoke the HttpResponse it just creates an empty instance, it contains nothing, and I don't understand why it does so.
Any help appreciated! Here's the code:
class HttpResponse {
constructor(status: number = 0,
data: string = '',
headers: Object = '',
error: string = ''){}
}
class Page {
response: HttpResponse;
retrieveData(): void {
document.body.innerHTML += 'inside retrieveData()<br>';
let data = {
status: 200, data: "this is some fake data",
headers: { foo: 'foo', bar: 'bar', baz: 'baz' }
}
document.body.innerHTML +='Data: ' + JSON.stringify(data) + '<br>';
this.response = new HttpResponse(data.status, data.data, data.headers);
document.body.innerHTML += JSON.stringify(this.response);
}
}
new Page().retrieveData();
In the constructor of your HttpResponse class, you are not setting the properties of the class with the passed arguments. You can do so by using the public qualifier in the parameters.
class HttpResponse {
constructor(public status: number = 0,
public data: string = '',
public headers: Object = '',
public error: string = ''){ }
}
See the updated Fiddle.
Alternatively, you can declare the properties in your class and set them in the constructor like this.data = data; assignments.
Because your HttpResponse does not actually have any properties. You only have constructor parameters and nothing else. If you want to automatically convert your constructor parameters into properties, you can do so by using parameter properties:
class HttpResponse {
constructor(
public status: number = 0,
public data: string = '',
public headers: Object = '',
public error: string = ''){}
}
You must have to declare constructor parameters using qualifiers i.e. private public protected
class HttpResponse {
constructor(
private status: number = 0,
private data: string = '',
private headers: Object = '',
private error: string = ''){}
}
Related
I am having a little problem while sending data from my React app to my Spring Boot Controller, I am sending the data via a put method, but I get 400, error, and an error in eclipse pops up, so What I did is :
export const changeContratTypes = (idContrat, items, declaration) => {
const endpoint = template(CONTRAT_TYPES_CHANGE);
return instance // just an axios instance
.put(endpoint({ idContrat }), { items, declaration })
.then(values => values)
.catch(err => err.response);
};
My endpoint constant is the url, simple is that, and I send declaration which is an integer and items which is an array of object, my object structure is :
{
id: 1, // or 2, 3, ....
isSelected: true, // or false
title: "a String here"
}
To get this in Spring boot I created this method in my controller :
#CrossOrigin(origins = "*")
#ApiOperation(value = "${contrat.recuperation}", notes = "${contrat.recuperation.notes}", response = ContratDetailDto.class)
#PutMapping(value="/{idContrat}/trtype")
#ApiModelProperty(example = "4000004")
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Enrigistrer Les types de contrats ") })
public ResponseEntity enrigistrerTypesDeContrat(#ApiParam(value = "${contrat.recuperation.param.id}") #PathVariable long idContrat, #RequestBody TypesConformites tcf) {
if (log.isDebugEnabled()) {
log.debug("appel de la méthode enrigistrerTypesDeContrat");
}
System.out.println("Voila "+tcf.getDeclaration());
return ResponseEntity.ok(HttpStatus.OK);
}
This controller is well mapped and other methods in it works fine, but all methods I used are Get Methods.
What I did before that is creating a class used as a RequestBody :
#Getter #Setter
public class TypesConformites {
private int declaration;
private ArrayList<Item> items;
public TypesConformites() {
}
}
and Here is my Item class :
#Getter #Setter
public class Item {
private int id;
private String title;
private boolean isSelected;
public Item() {
}
}
I get this error in Java :
Blockquote
JSON parse error: Unrecognized field "isSelected" (class com.apicil.cosy.contrat.controller.api.impl.external.Item), not marked as ignorable; nested exception is com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "isSelected" (class com.apicil.cosy.contrat.controller.api.impl.external.Item), not marked as ignorable (3 known properties: "title", "id", "selected"])
at [Source: (PushbackInputStream); line: 1, column: 66] (through reference chain: com.apicil.cosy.contrat.controller.api.impl.external.TypesConformites["items"]->java.util.ArrayList[0]->com.apicil.cosy.contrat.controller.api.impl.external.Item["isSelected"])
What's wrong with that code, Any help would be much appreciated.
Generally the Item is deserialised by jackson like this :-
public void setId(String firstName) {
public void setTitle(String lastName) {
public void setSelected(boolean isActive) {
To avoid this you can just changed the mapping name in the Item and request body.. or annotated your isSelected with #JsonProperty
My requirement is to pass multiple class object(which is going to map with request param or request body in rest controller) in angular $http service.
I can't pass class object in request body since one http call has only one request body.
When i'm trying to pass class object in $http param I'm getting class cast exception.
is there any way to pass multiple object in single $http call ??
#RequestMapping(value = "CommitObject", method = RequestMethod.POST)
public void Commit(#RequestParam(value = "clazz") final String clazz,
#RequestParam(value = "Id") final String modelId,#RequestBody LinkedHashMap<String, Object> obj) {
mService.Commit(Id,clazz workingmodelObj);
}
I tried it many times but always failed.So to overcome this I use to create a Java Bean and encapsulate both objects into it at then accepting it in #RequestBody.
Your Wrapper should look like this:
public class SampleWrapper {
private Object1 object1;
private Object2 object2;
//getters setters and constructors go here
}
And your constructor should look like this:
#RequestMapping(value = "/url",method= RequestMethod.POST)
public String getRequest(#RequestBody SampleWrapper wrapper) {
Object1 o1 = wrapper.getObject1();
Object2 o2 = wrapper.getObject2();
}
JSON request should look like this:
{
"object1" : {//object1 body },
"object2" : {//object2 body }
}
If you're trying to make a $http.post request you can make an array of the objects you are trying to send and then attach it in the request.
$http.put('ROUTE HERE', Array Of Objects);
You can pass Objects by appending it in formData
Angular side
var formData=new FormData();
formData.append("obj1",new Blob([JSON.stringify(obj1)],{type: "application/json"}));
formData.append("obj2",new Blob([JSON.stringify(obj2)],{type: "application/json"}));
http({
method: 'POST',
url: '/MyProject/requestUrl',
headers: { 'Content-Type': undefined},//to set boundary value by default
data: formData,
})
Spring side
#RequestMapping(value = { "/requestUrl" }, consumes = { "multipart/form-data" }, method = RequestMethod.POST)
#ResponseBody
public String getRequest(#RequestPart("obj1") Object1 object1,
#RequestPart("obj2") Object2 Object2,HttpSession session)
throws IOException {
//implementation
}
I have the following method in a service I've created:
getPost(nid: string): Observable<Post[]>{
let url = "http://test.co.uk/api/v1/basic/" + nid;
return this.http.get(url, {headers: this.headers}).map(res => res.json() as Post).catch(err => {
return Observable.throw(err);
});
}
And this is the class of my component:
export class PostDetailComponent implements OnInit {
posts: Post[] = [];
post: Post = new Post();
constructor(
private route: ActivatedRoute,
private postService: PostService
) { }
ngOnInit() {
this.route.params.switchMap((params: Params) => {
let nid = params ['nid'];
return this.postService.getPost(nid); }).subscribe(res => {
console.log(res)
this.post = res as Post;
}, err =>{
console.log(err);
});
}
}
The JSON feed looks like this(yes one object in the array):
[
{
"nid":"3",
"title":"When Unity meets Vuforia",
"body":"<p>Unless you have been living under a rock in the past 7 - ...",
"uid":"admin",
"path":"\/node\/3",
"field_article_image":"http:\/\/test.co.uk\/sites\/default\/files\/when-unity-meets-vuforia_0.jpg?itok=BGYaotay"
}
]
So in my template, if I print {{post}} I get [object Object] on the screen.
If I print {{post | json}} I get the row JSON feed.
And finally, if I print {{post.title}} or {{post?.title}} I don't get anything.
I also have a class Post that is looking like this:
export class Post{
constructor(
public nid?: string,
public title?: string,
public body?: string
public image?: string
){
}
}
Any hints?
You are assigning an array into what should be a single object. Copy the first element of the array into the post variable
this.post = res[0] as Post
Side note: It's incorrect to assign a raw object to a class instance. In this case, your this.post.constructor won't exist and this.post instanceof Post == false.
You could do Object.assign(this.post, res[0]) but you may need to clear existing properties if not all properties are always present.
I prefer to define object shapes as interfaces instead, then you would not have that problem because all the interface information is removed at runtime, whereas a class does emit some code instead of just doing static type checks at compilation time
I'm trying to post a object that includes an id (int) and a array, but I get a http 400 Bad request response from the server side. This is what I have so far...
Java Bean Object for Request:
public class GuardarVentaRequest {
private Integer idCliente;
private List<Venta> venta; ... (Getters and Setters code)
Java Object:
public class Venta {
private Integer id;
private String nombre;
private Integer precio;
private Integer cantidad;
private Integer total; ... (Getters and Setters code)
Java Controller:
#RequestMapping(value = "/guardarVenta", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody void venta(#RequestBody GuardarVentaRequest factura){
System.out.println(factura);
}
AngularJS Service:
function guardarVenta(array){
let factura = {
idCliente : parseInt($('#cliente').val()),
venta : array,
};
console.log(factura);
$http({
method: 'POST',
url: '/blue/guardarVenta',
contentType: 'application/json',
data: factura
}).then(
function successCallback(response){
console.log(response.statusText);
},
function errorCallback(response){
console.log(response.statusText);
}
);
}
Array:
$scope.productos = new Array();
let productoInfo = {
id: $scope.producto.id,
nombre: $scope.producto.nombre,
precio: $scope.producto.precio,
cantidad: $scope.cantidadProducto,
total: $scope.producto.precio * $scope.cantidadProducto
}
$scope.productos.push(productoInfo);
Output:
ADVERTENCIA: Failed to read HTTP message:
org.springframework.http.converter.HttpMessageNotReadableException: Could
not read document: Can not construct instance of com.blue.beans.Venta: no
suitable constructor found, can not deserialize from Object value (missing
default constructor or creator, or perhaps need to add/enable type
information?)
at [Source: java.io.PushbackInputStream#663359f3; line: 1, column: 28]
(through reference chain: com.blue.beans.GuardarVentaRequest["venta"]-
>java.util.ArrayList[0]); nested exception is
com.fasterxml.jackson.databind.JsonMappingException: Can not construct
instance of com.blue.beans.Venta: no suitable constructor found, can not
deserialize from Object value (missing default constructor or creator, or
perhaps need to add/enable type information?)
at [Source: java.io.PushbackInputStream#663359f3; line: 1, column: 28]
(through reference chain: com.blue.beans.GuardarVentaRequest["venta"]-
>java.util.ArrayList[0])
Chrome's Network Tab Output
Any ideas?
Try these 3 things.
Add the default constructor to GuardarVentaRequest and Venta.
GuardarVentaRequest(){} &
Venta(){}
Check if a HTTPMessageConverter has been added to your spring config. Eg: MappingJackson2MessageConverter (Check for compatibility with your spring version).
Try serializing the request payload by using angular.toJson
Hope that helps!
I want to call a web service method in javascript. (asp.net 3.5)
I have traced the result with firebug .
here is the result:
{"d":"[{\"TI\":\"www\"},{\"TI\":\"www1\"}]"}
I think the correct result should like this
{"d":[{\"TI\":\"www\"},{\"TI\":\"www1\"}]}
what is the quotation before and after the Bracket ?
// edited :
in webserivce:
public class Test
{
public Test(string t){T1 = t;}
public string T1 { set; get; }
}
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true, XmlSerializeString = false)]
public string Load(string e)
{
List<Test> post = new List<Test> { new Test("www"), new Test("www1") };
return JsonConvert.SerializeObject(post);
}
and in js file :
var store = new Ext.data.JsonStore({
proxy: new Ext.data.HttpProxy({
url: '/core/webservice/service.asmx/Load',
method: 'GET',
headers: { 'Content-type': 'application/json' }
}),
root: 'd',
id: 'Id',
fields: ['TI']
});
store.load({ params: { e: ''} });
return;
thank you .
mir
You shouldn't need to serialize manually in the web service; consider using something like this instead:
public List<Test> Load(string e)
{
List<Test> post = new List<Test> { new Test("www"), new Test("www1") };
return post;
}
Since you're using string as your return object, it will convert it as that for you when serializing it (once again).
The quotation indicates that this is a string, so :
var b = {"d":"[{\"TI\":\"www\"},{\"TI\":\"www1\"}]"};
b["d"] will return a string instead of array of objects.
You can either go around this with the following in javascript:
var c = eval(b["d"]);
which will turn the string into an array of objects.
Or the better way, post the code that is returning this and we can try to figure out why it is returned as a string.