0

I am trying to consume a Spring boot webfulx reactive api in my angular but I am getting below error in browser developer console.

{error: SyntaxError: Unexpected token { in JSON at position 231 at JSON.parse

The api produces application/x-ndjson and I am not sure if HttpClient is unable to parse the response.

My Service Class:

export class UserInfoService {
  private baseUrl = "http://localhost:9095/api/userinfo";

  private headers= new HttpHeaders()
    .set('content-type', 'application/json')
    .set('Access-Control-Allow-Origin', '*')

  constructor(private http: HttpClient) {}

  getUsers(): Observable<UserInfo[]> {
    return this.http.get<UserInfo[]>(
      this.baseUrl + '/users', {'headers':this.headers});
  }
}

My component class

export class DashboardComponent implements OnInit {
  count: any = 0;
  service: HttpServiceService;
  usersList: Array<UserInfo> | undefined;

  constructor(service: HttpServiceService) {
    this.service = service;
  }

  ngOnInit(): void {
    console.log("---ngOnInit()---");
    this.service.getUsers().subscribe({
      next: (result: any) => {
        console.log("||||Response successful");
        this.usersList?.push(result);
        console.log(result);        
      },
      error: (err: any) => {
        console.log(err);
      },
      complete: () => {
        console.log('complete');
      }
    });
  }
}

I want to display the data in the template table reactively. I see the below error in browser console:

@GetMapping(path="/users", produces = "application/x-ndjson")
public Flux<UserInfo> getAll() {
    return userInfoService.getAll();
}

enter image description here

Thomson Mathew
  • 419
  • 1
  • 9
  • 28
  • I think you need to read the result as text and not as json, then use https://www.npmjs.com/package/ndjson-rxjs to stream/read it to angular. – Get Off My Lawn Aug 01 '22 at 03:18

1 Answers1

0

ndjson format is not a valid application/json format and that's why you get that error when the HttpClient tries to parse the response.

The solution for this is to request the content as plain text and parse the content afterwards. You can achieve this by sending responseType: 'text' when making the request:

export class UserInfoService {
  private baseUrl = "http://localhost:9095/api/userinfo";

  private headers= new HttpHeaders()
    .set('Access-Control-Allow-Origin', '*')

  constructor(private http: HttpClient) {}

  // here is a simple ndjson parser implementation I found:
  parse(data: string): any[] {
    if (typeof data !== 'string')
      throw new Error(`Unexpected type ${type}`);
    const rows = data.split(/\n|\n\r/).filter(Boolean);
    return rows.map((row) => JSON.parse(row));
  }

  getUsers(): Observable<UserInfo[]> {
    return this.http.get<UserInfo[]>(this.baseUrl + '/users', {
      headers: this.headers,
      responseType: 'text'
    }).pipe(map(this.parse));
  }
}
Mauro Aguilar
  • 1,093
  • 13
  • 22