22
33const Transform = require ( 'stream' ) . Transform ;
44
5+ const JSONUnexpectedTokenRe = / ^ U n e x p e c t e d t o k e n ( .) i n J S O N a t p o s i t i o n ( \d + ) $ / ;
6+
57/**
68 * JSONTransform
79 */
@@ -26,19 +28,27 @@ class JSONTransform extends Transform {
2628 this . _countBy = countBy ;
2729 this . _expanding = expanding ;
2830 this . _items = [ ] ;
31+ this . _buf = '' ;
2932 }
3033
3134 _transform ( chunk , encoding , cb ) {
35+ this . _buf += chunk . toString ( ) ;
36+
3237 try {
33- const data = JSON . parse ( chunk ) ;
34- if ( this . _expanding && ( data instanceof Array ) ) {
35- this . _items = this . _items . concat ( data ) ;
36- } else {
37- this . _items . push ( data ) ;
38- }
38+ const data = JSON . parse ( this . _buf ) ;
39+ this . _pushItemsFromData ( data ) ;
40+ this . _buf = '' ;
3941 } catch ( err ) {
40- cb ( err , null ) ;
41- return ;
42+ if ( ! ( err instanceof SyntaxError ) ) {
43+ return cb ( err ) ;
44+ }
45+
46+ const r = this . _rescueJSONError ( err ) ;
47+ if ( r === 'next' ) {
48+ return cb ( ) ;
49+ } else if ( r === 'error' ) {
50+ return cb ( err ) ;
51+ }
4252 }
4353
4454 while ( this . _items . length >= this . _countBy ) {
@@ -47,6 +57,39 @@ class JSONTransform extends Transform {
4757 cb ( ) ;
4858 }
4959
60+ _rescueJSONError ( err ) {
61+ const errMsg = err . message ;
62+ if ( errMsg === 'Unexpected end of JSON input' ) {
63+ // JSON unfinished
64+ return 'next' ;
65+ }
66+
67+ const md = JSONUnexpectedTokenRe . exec ( errMsg ) ;
68+ if ( md ) {
69+ const pos = Number ( md [ 2 ] ) ;
70+ if ( md [ 1 ] === '{' ) {
71+ // another JSON follows
72+ const data = JSON . parse ( this . _buf . substr ( 0 , pos ) ) ;
73+ this . _pushItemsFromData ( data ) ;
74+ this . _buf = this . _buf . substr ( pos ) ;
75+ return 'continue' ;
76+ } else if ( this . _buf . substr ( pos - 1 , 1 ) === '"' ) {
77+ // JSON unfinished
78+ return 'next' ;
79+ }
80+ }
81+
82+ return 'error' ;
83+ }
84+
85+ _pushItemsFromData ( data ) {
86+ if ( this . _expanding && ( data instanceof Array ) ) {
87+ this . _items = this . _items . concat ( data ) ;
88+ } else {
89+ this . _items . push ( data ) ;
90+ }
91+ }
92+
5093 _flush ( cb ) {
5194 const items = this . _items ;
5295
0 commit comments