New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(common): support custom JSON parser in HttpClient #25027
Conversation
6ed46ea
to
18ad2a9
Compare
18ad2a9
to
31a9d98
Compare
What should be done to accept this PR? |
31a9d98
to
65a7751
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@trotyl thanks for this PR. I am sorry it slipped under our radar for so long. I rebased it and cleaned up the conflicts. But I have a few suggestions for how to make it a bit slimmer.
@@ -70,7 +77,8 @@ interface PartialResponse { | |||
*/ | |||
@Injectable() | |||
export class HttpXhrBackend implements HttpBackend { | |||
constructor(private xhrFactory: XhrFactory) {} | |||
constructor(private xhrFactory: XhrFactory, @Inject(JSON_PARSER) private jsonParser: JsonParser) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about making this optional, then we wouldn't have to define a provider for the default case:
constructor(private xhrFactory: XhrFactory, @Inject(JSON_PARSER) private jsonParser: JsonParser) { | |
constructor(private xhrFactory: XhrFactory, @Optional() @Inject(JSON_PARSER) private jsonParser?: JsonParser) { | |
if (jsonParser == null) { // note == matches both `null` and `undefined` | |
this.jsonParser = JSON; | |
} |
@@ -33,7 +33,7 @@ const XSSI_PREFIX = ')]}\'\n'; | |||
let backend: HttpXhrBackend = null!; | |||
beforeEach(() => { | |||
factory = new MockXhrFactory(); | |||
backend = new HttpXhrBackend(factory); | |||
backend = new HttpXhrBackend(factory, JSON); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If jsonParser
was optional this would not need to change.
@@ -16,6 +16,13 @@ import {HttpDownloadProgressEvent, HttpErrorResponse, HttpEvent, HttpEventType, | |||
|
|||
const XSSI_PREFIX = /^\)\]\}',?\n/; | |||
|
|||
/** | |||
* Utility for parsing JSON text to JavaScript object |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we would need a bit more documentation for this and the JSON_PARSER
token below, ideally with an example and referencing each other.
export function _JSON(): JsonParser { | ||
return JSON; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If jsonParser
was optional then this would not be needed.
We discussed this in the team meeting yesterday. The general consensus is that this is actually fairly straightforward to do via an interceptor and that the real problem is the lack of discoverability of this approach to solving the problem. We accept that the problem is compounded by the fact that HttpClient defaults to json parsing with its own parser and so the natural solution that people lean towards is replacing this built-in JSON parsing directly. It would have been better if the default had been text so that JSON parsing felt more like a special case that would lead more naturally to overriding via an interceptor. The proposal then, is not to merge this feature into core, but instead to improve the documentation to lead developers clearly to an interceptor based solution. Here is a link to an example of how custom JSON parseing could be done in a reusable interceptor: https://stackblitz.com/edit/angular-ivy-nrdj5q?file=src%2Fapp%2Fapp.module.ts. Note that this could be wrapped up and distributed as a 3rd party library and then the application developer would only need to provide their own JsonParser class. |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
closes #21079
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
What is the current behavior?
Issue Number: #21079
When user works with an extended JSON format, eg. JSON5, due to it's not compatible with
JSON.parse()
, user have to make it raw text and parse it manually.But JSON5 format is still conceptually
'json'
rather than'text'
, it's a fully superset of ES JSON, just being more human friendly.What is the new behavior?
Simply with:
Or strip a different receiver:
Or have a different reviver:
Then server could provide JSON5 response directly and no error would be raised.
Does this PR introduce a breaking change?
Other information