skip to Main Content

I used to parse JSON to list of objects by the following way:

final response = await api(map);
var raw = jsonDecode(response.body)[0];
dataList = parseJson(raw["datalist"]);

List<dataRecord> parseJson(String responseBody) {
    final parsed = convert.jsonDecode(responseBody).cast<Map<String, dynamic>>();
    return parsed.map<dataRecord>((json) => dataRecord.fromJson(json)).toList();
  }

and the JSON is in this format:

datalist: [{"id": 29737, "rent": 700, "unit": "A", .....

this works fine in all of my existing projects.

However, I am now retrieving data from an external source and the JSON is in this format:

data: [{id: 4109486, unicorn_id: 7836045, memorial_id: 23072601320076, ...

field labels and string values all without quotes, and I am not able to use the same parseJson function to parse the JSON.

2

Answers


  1. Use this method to add quotes around the keys and string values in the response.

    String preprocessResponse(String responseBody) {
      final processedResponse = responseBody.replaceAllMapped(
        RegExp(r'(w+):'),
        (match) => '"${match.group(1)}":',
      );
    
      return '{"datalist": [$processedResponse]}';
    }
    
    Login or Signup to reply.
  2. One possible way is to add a hook to the JSON parser.
    First hook to parse _keyValue.
    The second hook is to parse _string.

    This allows you to parse regular JSON and JSON that uses identifiers as object keys.

    import 'package:parser_combinator/extra/json_parser.dart' as json_parser;
    import 'package:parser_combinator/parser/predicate.dart';
    import 'package:parser_combinator/parser/recognize.dart';
    import 'package:parser_combinator/parser/skip_while.dart';
    import 'package:parser_combinator/parser/skip_while1.dart';
    import 'package:parser_combinator/parser_combinator.dart';
    import 'package:parser_combinator/parsing.dart';
    import 'package:parser_combinator/runtime.dart';
    import 'package:parser_combinator/tracing.dart';
    
    void main(List<String> args) {
      const raw1 = '''
    data: [{id: 4109486, unicorn_id: 7836045, memorial_id: 23072601320076}]
        ''';
    
      const raw2 = '''
    "data": [{"id": 4109486, "unicorn_id": 7836045, "memorial_id": 23072601320076}]
        ''';
    
      final input1 = '{$raw1}';
      final r1 = _parse(input1);
      print(r1);
    
      final input2 = '{$raw2}';
      final r2 = _parse(input2);
      print(r2);
    }
    
    bool _isAllowedChar(int c) => c == 0x5f;
    
    bool _isIdentEnd(int c) => _isIdentStart(c) || isDigit(c);
    
    bool _isIdentStart(int c) => isAlpha(c) || _isAllowedChar(c);
    
    Object? _parse(String input) {
      const ident = Recognize2(SkipWhile1(_isIdentStart), SkipWhile(_isIdentEnd));
    
      var stringCount = 0;
      Result<O>? parse<O>(Parser<String, O> parser, State<String> state) {
        final name = parser.name;
        if (name == '_keyValue') {
          stringCount = 0;
        }
    
        final result = parser.parse(state);
        if (name == '_string') {
          stringCount++;
          if (result == null && stringCount == 1) {
            final result2 = ident.parse(state);
            if (result2 != null) {
              return result2 as Result<O>;
            }
          }
        }
    
        return result;
      }
    
      bool fastParse<O>(Parser<String, O> parser, State<String> state) {
        return parser.parse(state) != null;
      }
    
      final builder = TracerBuilder(
          fastParse: fastParse,
          parse: parse,
          filter: <O>(parser) {
            return parser.name == '_keyValue' || parser.name == '_string';
          });
      final p = builder.build(json_parser.parser);
      return parseString(p.parse, input);
    }
    
    

    Output:

    {data: [{id: 4109486, unicorn_id: 7836045, memorial_id: 23072601320076}]}
    {data: [{id: 4109486, unicorn_id: 7836045, memorial_id: 23072601320076}]}
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search