Flutter Error: The method 'jsonEncode' is not defined - json

I am attempting to create a put request to an API using Flutter using the following function:
Future<http.Response> login(String username, String password) {
return http.put(
Uri.parse('apiurl'),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(
<String, String>{'username': username, 'password': password}));
}
The issue I am running into is that it keeps erroring out at the jsonEncode line, saying it is not defined. I have included the following packages:
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
What am I missing to make the jsonEncode function exist?

You need to import:
import "dart:convert";
Dart-convert-library

At the top of your file, add this import:
import "dart:convert";
as you can see from its documentation, it belongs to the dart's convert package:
jsonEncode
jsonDecode

Related

Wp api for flutter

I am trying to use the wordpress api, but it throws me an error when entering the url.
Error: The argument type "String" can't be assigned to the parameter type Uri
Could someone explain the error to me and tell me how the code should look? Thanks
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<List> blog() async {
final response = await http.get(('https://bauk.blog/wp-json/wp/v2/posts?_embed': {"Accept": "application/json"}));
var convertirajson = jsonDecode(response.body);
return convertirajson;
}
You need to parse the url before passing it to http.get()
For that declare your url variable like this:
var url = Uri.parse('https://bauk.blog/wp-json/wp/v2/posts?_embed');
And then pass it to http.get() like this
http.get((url: {...} ));

Angular Unexpected token c in JSON at position 0 at JSON.parse when expecting a string

I am not sure what I am doing wrong here.
I am trying to use the checkout facility for stripe using this documentation: https://stripe.com/docs/payments/checkout/accept-a-payment
I have configured my API to just return the checkoutid as a string.
The Angular service just calls the controller. When I run my code I actually get a nice 200 response and I can see the checkout id in the response body, but Angular throws an error:
SyntaxError: Unexpected token c in JSON at position 0 at JSON.parse () at XMLHttpRequest.onLoad (https://127.0.0.1:4200/vendor.js:18780:51) at ZoneDelegate.invokeTask
The service looks like this:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { map } from 'rxjs/operators';
import { environment } from '#environments/environment';
#Injectable({
providedIn: 'root',
})
export class StripeService {
private endpoint: string = 'stripe';
constructor(private http: HttpClient) {}
checkout(priceId: string) {
return this.http
.get<string>(`${environment.apiUrl}/${this.endpoint}/${priceId}`)
.pipe(
map((response) => {
console.log(response);
return response;
})
);
}
}
and I am invoking it like this:
this.stripeService
.checkout(this.button.priceId)
.subscribe((checkoutId: string) => {
console.log(checkoutId);
// this.stripe
// .redirectToCheckout({
// sessionId: checkoutId,
// })
// .then(function (result) {
// // If `redirectToCheckout` fails due to a browser or network
// // error, display the localized error message to your customer
// // using `result.error.message`.
// });
});
If I look in the network tab I can see this:
But the console actually shows this:
Does anyone have a scooby why?
Probably the response is a string and you haven't specified the response type. Try the following
this.http.get(
`${environment.apiUrl}/${this.endpoint}/${priceId}`,
{ responseType: 'text' }
)
Default response type is json.
It happened to me when my API return doesent match with my deserializable object on Angular. At first, try to check your returns entities

How to intercept call and serve back JSON file dynamically (without "import")

I have a scaffolding of folders and json files to mock an API's paths. When I run npm run start:mock, LocalMockInterceptor gets provisioned and e.g. replaces a call to host/A/B/C by an http call getting locally Folder A/Folder B/C.json. The JSON files get produced by a separate script which is out of scope here. I cannot make use of "import" as many tutorials show because I need a generic solution as the API i am mocking will evolve over time (and so will this scaffolding of folders and files).
/**
* The idea is to only build this into the bundle if we specify so (e.g. on TeamCity, on your localhost), where you don't want to rely
* on external resources for development
* No conditionals in the code bundle! No configuration files or database dependency.
*/
import {
HttpInterceptor,
HttpResponse,
HttpHandler,
HttpRequest,
HttpEvent,
HttpClient,
HttpHeaders
} from '#angular/common/http';
import { Injectable, Injector } from '#angular/core';
import { Observable, of } from 'rxjs';
import { ErrorService } from './error.service';
const devAssetsFolder = 'assets';
#Injectable()
export class LocalMockInterceptor implements HttpInterceptor {
constructor(
private errorService: ErrorService,
private injector: Injector,
private http: HttpClient
) {}
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
if (request.url.endsWith('.json')) return next.handle(request);
console.log(
` >>> Mock Interceptor >>> ${request.url} has been intercepted`
);
const path = `${devAssetsFolder}${request.url}.json`;
var promise = this.getJSON(path).toPromise();
const jsonheaders = new HttpHeaders();
jsonheaders.set('Content-Type', 'application/json');
let json2;
promise
.then(json => {
console.log(json);
json2 = json;
})
.catch(error => console.log(error));
Promise.all([promise]);
console.log(json2);
return of(
new HttpResponse({ status: 200, body: json2, headers: jsonheaders })
);
}
private getJSON(jsonPath: string): Observable<any> {
return this.http.get(jsonPath);
}
}
The first conditional is to avoid infinite loops since I am sending HTTP requests in my interceptor
Getting the path to the JSON file based on the URL is quite natural
It seemed to me that I have to convert the JSON Observable into a promise so that I can wait for it to complete before rewrapping that json into the returned Observable. When debugging however, it seems Promise.all is not waiting for the promise to complete (json2 is undefined on the next line), and I end up sending an empty http body back...
How to fix this rxjs promise ?
Is inner HTTP calls my only option ?
Is there a way not to rely on promises ? Can you think of a better way to achieve this ?
Did you try just modifying the target URL in your interceptor ? You want to make an API call that return some JSON but instead of calling a dynamic API, you just want to call you static server so it can return predefined JSON.
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
const fakeUrl = `${devAssetsFolder}${request.url}.json`;
const fakeRequest = request.clone({url: fakeUrl});
return next.handle(request);
}
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
if (request.url.endsWith('.json')) return next.handle(request);
console.log(
` >>> Mock Interceptor >>> ${request.url} has been intercepted`
);
const path = `${devAssetsFolder}${request.url}.json`;
return this.getJSON(path).pipe(map(result => {
const jsonheaders = new HttpHeaders({ 'Content-Type': 'application/json' });
return
new HttpResponse({ status: 200, body: result, headers: jsonheaders });
}), // you can also add catchError here
);
}
In intercept method you can return an observable. So your getJSON method returns an observable, we added pipe a map function which maps the result to new http response. If your response already has the right headers you don't even need the pipe and map functions you can just do this :
return this.getJSON(path); // it's an observable, so it's OK.

Get json Data from Rapid API in Flutter (Dart)

I managed to load the data from a Json File which is local on my Flutter Project. I also was able to fetch Data from the Internet, if the API Url was like:
https://[API-Server][parameter1:xy][parameter2:abc][API-KEY:lasgoewrijeowfjsdfdfiia]
I archieved that with this code sample:
Future<String> _loadStringFixtures() async {
return await rootBundle.loadString('assets/fixtures.json');
}
Future loadFixtures() async {
String jsonString = await _loadStringFixtures();
final jsonResponse = json.decode(jsonString);
FixturesAPI value = new FixturesAPI.fromJson(jsonResponse);
return value;
}
So far so good...
But now I am facing a problem with the API Provider RapidAPI
You can find the documentation etc. here:
https://rapidapi.com/api-sports/api/api-football/endpoints
As you can see they give some code snippets to connect to their API.
There are some for C, C#, Java, Python etc. You can look into all of them with the link above.
Sadly there is no example for Flutter.
And I do not see a way to adapt these examples.
Normally you can paste your API Key directly into the URL, but this seems not possible here? Or maybe it is?
Does Flutter also have other possibilities to receive data from an API besides the one I did?
Thank you so much in advance for your help!
It's possible to with http package and very easy. You can see in this example below...
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
class APIService {
// API key
static const _api_key = <YOU-API-KEY-HERE>;
// Base API url
static const String _baseUrl = "api-football-beta.p.rapidapi.com";
// Base headers for Response url
static const Map<String, String> _headers = {
"content-type": "application/json",
"x-rapidapi-host": "api-football-beta.p.rapidapi.com",
"x-rapidapi-key": _api_key,
};
// Base API request to get response
Future<dynamic> get({
#required String endpoint,
#required Map<String, String> query,
}) async {
Uri uri = Uri.https(_baseUrl, endpoint, query);
final response = await http.get(uri, headers: _headers);
if (response.statusCode == 200) {
// If server returns an OK response, parse the JSON.
return json.decode(response.body);
} else {
// If that response was not OK, throw an error.
throw Exception('Failed to load json data');
}
}
}
Then get you request:
//....
APIService apiService = APIService();
// You future
Future future;
//in the initState() or use it how you want...
future = apiService.get(endpoint:'/fixtures', query:{"live": "all"});
//....
Yes it possible in flutter. Use the Dio Package in flutter which is a powerful Http client. Using dio you can set interceptors to add api key to url so you don't have to append it in every request. Setting interceptors will help you.

Angular 4 custom http interceptor. localStorage.getItem() returns null

I am using Azure B2C authentication. Upon successful redirect, the access token gets stored in browser's localStorage and for subsequent API calls, following http interceptor class is supposed to attach the auth token to all outbound requests. Issue is that localStorage.getItem() returns null when trying to read auth token from localStorage. Here is the code,
import { HttpClient, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest }
from '#angular/common/http';
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs/Observable';
#Injectable()
export class HttpManagerInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
req = req.clone({ headers: req.headers.set('Accept', 'application/json') });
req = req.clone({ headers: req.headers.set('X-CRSP-TOKEN', 'ToBeImplemented') });
// this line always returns null
const authToken = window.localStorage.getItem('auth_token');
console.log('Inside http interceptor. Access token: ' + authToken);
if (authToken) {
req = req.clone({ headers: req.headers.set('Authorization', `Bearer
${authToken}`) });
}
console.log(JSON.stringify(req.headers));
return next.handle(req);
}
Console logs
Token found:
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1jNTdkTzZRR1RWQndhTmsifQ.eyJpc3MiOiJodHRwczovL2xvZ2luLm1pY3Jvc29mdG9ubGluZS5jb20vYmY5Njg3YWYtOTliMy00YzU3LWI2YjAtOWE5OGIzNTRhOWQyL3YyLjAvIiwiZXhwIjoxNTA0MTMxNzM3LCJuYmYiOjE1MDQxMjgxMzcsImF1ZCI6IjI4ZGM0NjZkLWRhZGUtNDNkMy04ZjBhLTJkYmNlNTQxYmIxMyIsIm9pZCI6IjcyMzljZWVjLTMzN2ItNDlmNS04YzViLTVkMzcwZGEwZmIxOCIsImdpdmVuX25hbWUiOiJaZWVzaGFuIiwiZmFtaWx5X25hbWUiOiJIYWlkZXIiLCJzdWIiOiJOb3Qgc3VwcG9ydGVkIGN1cnJlbnRseS4gVXNlIG9pZCBjbGFpbS4iLCJlbWFpbHMiOlsiWmVlc2hhbi5IYWlkZXJAY3JzcC5jaGljYWdvYm9vdGguZWR1Il0sImF6cCI6IjI4ZGM0NjZkLWRhZGUtNDNkMy04ZjBhLTJkYmNlNTQxYmIxMyIsInZlciI6IjEuMCJ9.DUebFoHuzLXIbjMOmRrCRYswMB1g-7J6kVOaYyI3-b5AuaTjrcTtTsZkiGbloseaKqKtKoRtO72EkyQ2XvJ2lyhCBybpD4skeOcwQ2p_RBcO1dlFSoWIOkQK7WPN_f3tLxzuvKgrcPuR2LurB_n0uEq8PTdMIKXgfuCVDUSjxGrcwlzGi61k2g24wzO-u9YdN5Xqx0eFqooE0hhiifTsAsXPNJhXTmLinr4qt25bRfvVs1UpYNk6hv1RQ3afrg7UZavr-Osjh5amQ6Qi_q6kKTQWorB9Cgoj_UTIA8ojkK-6y7D8uzY-YtLzomuNvD8mELCeZC8ZdPbbibzC2Kj6Rw
Inside http interceptor. Access token: null
I am suspecting if INTERCEPTORS initialized or created before localStorage is available to use. If that is the case and there is no workaround, can anyone suggest other solutions?
Your help will be appreciated!
Inject window inside your component
#Inject(WINDOW) private window: any