Unexpected token u in JSON at position 0 - angularjs

when I'm try to convert string to object I get error ``:
Unexpected token u in JSON at position 0
Service
setUser : function(aUser){
//sauvegarder User
localStorage.setItem('User', JSON.stringify(aUser));
},
getUser : function(){
//récuperer User
return JSON.parse(localStorage.getItem('User'));
}

The first thing to do is to look at what you're trying to parse. My guess is that you'll find it's "undefined", which is invalid JSON. You're getting undefined because you haven't (yet) saved anything to that key in local storage. undefined is then converted to the string "undefined" which JSON.parse can't parse.
I usually store and retrieve things in local storage like this:
Storing (just like yours):
localStorage.setItem("key", JSON.stringify(thing));
Retrieving (this is different):
thing = JSON.parse(localStorage.getItem("key") || "null");
if (!thing) {
// There wasn't one, do whatever is appropriate
}
That way, I'm always parsing something valid.

You are getting this error because you are not returning the response as a JSON string while your browser is expecting a JSON string to parse. Hence it is taking the first letter of your response string and throwing an error.
You can verify it by going to the networking tab of your browser's Dev tools and viewing the response.
To resolve this issue, you can use the code below in your http request.
var promiz = $http.post(url, data, {
transformRequest: angular.identity,
transformResponse: angular.identity,
headers: {
'Content-Type': undefined
}
});
Hope this helps!

I was also getting the same error. The problem was the response I was getting from HTTP Get Request was not in JSON format, Instead it was plain text.
this.BASE_URL = "my URL";
public getDocument() {
return this.http.get(this.BASE_URL)
.map((res: Response) => res.json())
.catch((error: any) => Observable.throw(error.json().error || 'Server error'));
}
So, the JSON Parser was throwing an error.
When I map it into plain text like this:
.map((res: Response) => res.text());
It works.

Related

React.js: Accessing the Retry-After header in an API response

I'm a newer programmer using React.js and the Spotify API for a music app. I’m trying to access the Retry-After header in a 429 rate-limiting error response (Spotify docs here). This is my code currently, which I loosely copied from this article.
async getArtistArt (artistID) {
let url = `https://api.spotify.com/v1/artists?ids=${artistID}`
let response = await fetch(url, {
headers: {
'Authorization': 'Bearer ' + localStorage.getItem('accessToken')
},
});
let data = await response.json();
if (Object.keys(data)[0] === "error" && data.error.status === 429) { // Handle rate limiting
console.log('Error!');
console.log(data);
for (var pair of data.headers.entries()) {
console.log(pair);
console.log(pair[0]);
}
}
return data;
}
This is what I see in the console:
screenshot here
console.log('Error!'); // Logs 'Error!'
console.log(data); // Logs error object, but not the header
console.log(pair) // Error that says 'Uncaught (in promise) TypeError: Cannot read property 'entries' of undefined'
I've tried not putting the response into json but that seemed to have no effect.
I've tried to avoid try/catch error statements as I’ve heard they’re somewhat outdated and not usually recommended, but would I need them to access the response header?
I would be grateful for any advice. A big thank you in advance!
I think I found where your error is. The code is almost correct except that you are checking for the headers in the json of the response.
Try to do for (var pair of response.headers.entries()) {...}, so that you are taking the response rather than its json content.

Upload file from AngularJS to Spring Boot

I'm using AngularJS to make my front end and Java with Spring Boot to make my back end. I'm trying to import/upload a xlsx, xls, or ods file from the Angular to my Java, but whatever I do, the request doesn't send my file!
Java endpoint:
#PostMapping(value = "/upload/{type}")
#ResponseBody
private ResponseEntity<List<Rota>> importFile(#PathVariable("type") String type,
#RequestParam(required = false, value = "file") MultipartFile fileParam,
#RequestBody MultipartFile file) {
System.out.println("File: " + file.getName());
if(type.toUpperCase().equals("XLSX")){
System.out.println("XLSX!");
}else if(type.toUpperCase().equals("XLS")){
System.out.println("XLS!");
}else if(type.toUpperCase().equals("ODS")){
System.out.println("ODS!");
}else{
System.out.println("OPS!");
return new ResponseEntity<>(new ArrayList<>(), HttpStatus.UNSUPPORTED_MEDIA_TYPE);
}
return new ResponseEntity<>(new ArrayList<>(), HttpStatus.OK);
}
My request-id made using an Angular class prepared to only make requests. I'll post here the code that we use normally in the project and the code that actually worked but I can't use it.
DataFactory:
DataFactory.POST = function (url, entity, config = null) {
if (url && entity) {
return $http
.post(url, entity, config)
.then(res => $q.resolve(res.data), error => $q.reject(error));
}
};
The code that actually worked:
var xhr = new XMLHttpRequest;
xhr.open('POST', `${URL.CTM_ODS()}/rotas/upload/${type}`, true);
xhr.send(formData);
When I use Postman, sending the file through the body, the back end receives null, but when I use form-data from Postman, works fine!
Using the DataFactory I got the following stack on my back end:
WARN 16796 --- [p1002886236-126] org.eclipse.jetty.http.HttpParser : badMessage: java.lang.IllegalStateException: too much data after closed for HttpChannelOverHttp#78fd8670{r=2,c=false,a=IDLE,uri=}
Found the answer in this video: https://www.youtube.com/watch?v=vLHgpOG1cW4
My problem was that the AngularJS deserialize the file! So, what I've made was just put a config object saying to not do that:
DataFactory.POST(`${URL.CTM_ODS()}/rotas/upload/${type}`, formData, { transformRequest: angular.indentity, headers: { 'Content-Type': undefined } }).then(response => {
delete vm.importacao.arquivoCsv;
console.log('Response: ', response);
LoadingManager.hide();
});
As you can see, the difference is on the header object, can you see that we pass the content type as undefined and transformRequest: angular.indentity? That worked for me! If anyone has other way to do so, feel free to comment! Thanks and have a nice day!

Modify Returned Response

I am trying to get a Session Key response to use in my future request inside a Zapier Session Authentication, however the response back from a successful authentication is "OK: hbsdakjdkaskjdfvbasdkjh". I need the hbsdakjdkaskjdfvbasdkjh extracted and then saved as the session key variable in the below zapier cli code
I am a little new to parsing JSON, but I think the response is actually raw... I tried a Regex but couldn't figure out the right statement and wondered if someone could help point me in the right direction.
The session URL params etc are working, and the Session Key responding after the OK: is actually correct and one I can use for the remainder of the session manually....
const options = {
url: 'https://theconsole.domain.com.au/api/auth.pl',
method: 'POST',
headers: {
'content-type': 'application/x-www-form-urlencoded',
'accept': 'application/json'
},
params: {
'AccountNo': bundle.authData.AccountNo,
'UserId': bundle.authData.UserId,
'Password': bundle.authData.Password
},
}
return z.request(options)
.then((response) => {
response.throwForStatus();
const results = z.JSON.parse(response.content);
// You can do any parsing you need for results here before returning them
return {
'sessionKey': results.sessionKey
};
});
Cool, so if your response is not json, you'll want to remove the z.JSON.parse line, since that'll throw an error.
As for pulling the key out of the response, success will depend on knowing that the response will always have a certain format. In this case, it sounds like it's OK: somekey.
If we can safely assume that there'll only ever be one space () and it's directly before the key, you can try something like:
// the rest of the code
respone.throwForStatus(); // important, assuming the server gives a non-2xx code for a bad auth
const sessionKey = response.content.split(' ')[1];
return {sessionKey}; // shorthand for {sessionKey: sessionKey}
Assuming those assumptions hold true, that should work!

Json Web Token - jose4j - SyntaxError: Unexpected token e in JSON at position 0

I have a controller which tries to get a token.
I got this error in postman when I execute it in the view PRETTY
Unexpected 'e'
But if I go to the view RAW I can see the token like this.
eyJraWQiOiIxIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJJc3N1ZXIiLCJhdWQiOiJBdWRpZW5jZSIsImV4cCI6MTQ3NTQ1OTMyNiwianRpIjoiTmF3d000bDVGRmFRZ0dBQkwzS3N5USIsImlhdCI6MTQ3NTQ1ODcyNiwibmJmIjoxNDc1NDU4NjA2LCJzdWIiOiJzdWJqZWN0IiwiZW1haWwiOiJtYWlsQGV4YW1wbGUuY29tIn0.f97SFDaAjUyUDK_UQgwgnCTewd0yw6tWK6DFLzpALFq177f1QMTYPbVdiIG1ViJ0FNJ6fUCleCd8BmrToUn25VSmRv799dtcz-xaN1kOgw90NQ00kPUhnDXG01-7hImkHfbmZZWORukP2yPK1sHWzpdjg9fJOvRZpZ6ZWli4HeuYRJqsFOv7PvwmGH9JnfRTf_2tboL-oAYBpT367eh60TggrvMgmrO_Taj5M7qGG0GpbwuVh_HTAkaKv7T2WmuZ2JPANhe5JvY_DDaqChtwd0IPREAhK3Xr-nTOIuwbQ0Y1hhOGfvDmikQj6DXnCERYixP6eR1dhC8n3bKvXyaVmA
This is the code of my controller.
#Path("/demo")
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response testMethod() throws JSONException, IOException {
RsaJsonWebKey rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);
rsaJsonWebKey.setKeyId("k1");
JwtClaims claims = new JwtClaims();
claims.setIssuer("Issuer");
claims.setAudience("Audience");
claims.setExpirationTimeMinutesInTheFuture(10);
claims.setGeneratedJwtId();
claims.setIssuedAtToNow();
claims.setNotBeforeMinutesInThePast(2);
claims.setSubject("subject");
claims.setClaim("email","mail#example.com");
JsonWebSignature jws = new JsonWebSignature();
jws.setPayload(claims.toJson());
jws.setKey(rsaJsonWebKey.getPrivateKey());
jws.setKeyIdHeaderValue(rsaJsonWebKey.getKeyId());
jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
String jwt = jws.getCompactSerialization();
if(jwt == null){
return Response.status(204).entity(jwt).build();
}
return Response.status(200).entity(jwt).build();
}
I ignore the error in postman but I get the same error when try to execute it in Chrome.
I try to call my RESTful controller with angular like this, but I always get into the onError method with the message within the response parameter.
angular.min.js:118 SyntaxError: Unexpected token e in JSON at position 0
This is the code in angular
app.service('TokenService', function($http){
this.getToken = function(){
function onSuccess(response){
console.log('got it');
}
function onError(response){
console.log('fail');
}
return $http({
method : 'GET',
url : 'http:localhost:8080/rest/demo',
header: {'Content-Type' : 'application/json'}
}).then(onSuccess, onError);
}
}
My reference of the code for the token is from here with Jose4j
UPDATE
I solved this. I still think the way I did it initially it should work also, but I don't still understand why I get the error.
I created a pojo named Token with a property token as String then I changed this
return Response.status(200).entity(jwt).build();
to this:
Token token = new Token();
token.setToken(jwt);
return Response.status(200).entity(token).build();
This is my workaround to return a real json object.
I know it's much too late now, but I've faced the same problem and got it fixed with your solution, so Thanks.
Just for the sake of whoever came across this issue later. In my case I do it like this.
HashMap<String, String> credential = new HashMap<>();
credential.put("token", jwtToken);
apiResp = ResponseEntity.ok(jwtToken);
Btw, I also seem to figured out the problem which is Angular might expect that response from server is JSON object by default then parse it to JavaScript object for us.
So we got our error because we return string as a response entity and it can't parse string to an object. That's why putting the token in POJO solved it.
The other way around is setting return type from client-side like this.
login(username: string, password: string): Observable<any> {
let body = {username, password};
let res = this.http.post(
`${API.AUTHENTICATION}`, body, {
responseType: 'text'
});
return res;
}
Now, JS will know that the response is of string type and it won't try to parse it to an object anymore.

415 (Unsupported Media Type) in $http.post method

I'm quite new to REST and AngularJS, but after several hours of googling I couldn't find any answer to my question:
I'm trying to do a POST request from my angularjs frontend to my backend implemented in java (using JPA).
When I'm trying to create a json-object and to do a POST I always get the 415 (Unsupported Media Type) error.
(Actually I don't even get "into" the scope of the service (i.E. "IN SERVICE" doesn't get printed to the console)..
If I add postData.toJSON(), it actually gets "POSTed", but arrives null ...
how do I have to format my 'postData' in Order to succesfully get POSTed?
(I also tried to write the Date-properties without ' " ' - no luck...)
Thank you for your help!
FrontEnd:
app.controller('WorkController', function($scope, $http) {
$scope.saveWork = function () {
var postData = {
"status" : "OPEN",
"startDate": "1338364250000",
"endDate": "1336364253400",
"WorkText" : "Test"
};
$http.post("http://localhost:8080/service/v1/saveWork", postData)
.success(function(data, status, headers, config){
console.log("IN SAVE WORK - SUCCESS");
console.log(status);
})
.error(function(){
console.log("ERROR IN SAVE WORK!");
})
}
});
Service:
#POST
#Consumes(MediaType.APPLICATION_JSON)
public Response save(WorkDto wo){
System.out.println("IN SERVICE");
if(ass == null){
System.out.println("Could nor persist work- null");
return Response.noContent().build();
} else{
Work workDao = WorkTransformator.transform(wo);
workDao.persist();
return Response.ok().build();
}
}
Instead of building and sending a parsed JSON object, create a javascript object and send that in your post body. You can reuse your postData object, but try removing the "" surrounding properties names.
Try this:
var postData = {
status : "OPEN",
startDate: "1338364250000",
endDate: "1336364253400",
workText : "Test"
};
UPDATE
Looks like the above doesn't work by itself. I thought that the Content-Type would be infered.
Can you try to do the post request this way :
$http({
method: 'POST',
url: 'http://localhost:8080/service/v1/saveWork',
data: postData,
headers: {
'Content-Type': 'application/json'
}}); // complete with your success and error handlers...
// the purpose is to try to do the post request explicitly
// declaring the Content-Type you want to send.
UPDATE 2
If this didn't work, compose a post request using Fiddler, and check what's the response.
Here's some pointers:
Download Fiddler2 if you dont already have it
Compose a request like in the screenshot below
You can then check on the pane on the left for what was the server response code. Double click that line (Ignore the error code on the screenshot...you should be getting a 415)
After double-clicking the response line, you can check and browse for more details on the right pane:
If you can successfuly post with a «manufactured» JSON object then the problem resides on your Angular code. If not, it's certainly something wrong with your Rest Service configuration.
You can also inspect the details of your POSTS made with the Angular app in Fiddler2. That should give you a good insight of what's going on.
If you're into it, you can then update your question with some screenshots of your Angular app requests. That will certainly help us to help you :)
I finally managed to find the cause of my error!
In my Rest-Service, I directly expected my java-class as parameter. (I thought this would be parsed/deserialized automatically). Quite naive I think... :)
In order to get it working I had to:
-Expect a String as Parameter in my #POST service
-Deserialize it (using GSON)
Here is the (now working) service:
#POST
#Consumes(MediaType.APPLICATION_JSON)
public Response save(String wo){
if(wo == null){
System.out.println("Could nor persist work- null");
return Response.noContent().build();
} else{
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HHmm:ssZ").create();
WorkDto dto = gson.fromJson(wo, WorkDto.class);
Work workDao = WorkTransformator.transform(dto);
workDao.persist();
return Response.ok().build();
}
}
Thanks again António for your help!

Resources