【问题标题】:Dart/flutter: How to fix "Unexpected character" error when serializing/de-serializing a map<> to json?Dart/flutter:如何在将 map<> 序列化/反序列化为 json 时修复“意外字符”错误?
【发布时间】:2020-08-25 23:32:47
【问题描述】:

能否请您帮忙并展示如何序列化和反序列化包含对象映射到/从 dart 中的 json 的类?

这是一个简单数据类的示例:

class SimpleData {
  int _blah;
  String _str;

  SimpleData([this._blah, this._str]);

  SimpleData.fromJson(Map<String, dynamic> json) {
    _blah = json['b'];
    _str = json['s'];
  }

  Map<String, dynamic> toJson() => {
    'b' : _blah,
    's' : _str,
  };
}

下面是SimpleData 在地图中的使用方式:

class MapTest {
  Map<String, SimpleData> _mapHell = Map<String, SimpleData>();

  MapTest() {
    _mapHell['1'] = SimpleData(42, "Astfgl");
    _mapHell['666'] = SimpleData(1234, "Vassenego");
  }

  MapTest.fromJson(Map<String, dynamic> json) {
    _mapHell = jsonDecode(json['coworkers']);
  }

  Map<String, dynamic> toJson() => {
    'coworkers' : jsonEncode(_mapHell),
  };
}

调用:print(mapTestInstance.toJson().toString()); 将输出:

{coworkers: {"1":{"b":42,"s":"Astfgl"},"666":{"b":1234,"s":"Vassenego"}}}

尝试反序列化失败,因为coworkers 应该被"" 包围。错误信息如下:

I/flutter (10196): Unexpected character (at character 2)
I/flutter (10196): {coworkers: {"1":{"b":42,"s":"Astfgl"},"666":{"b":1234,"s":"Vassenego"}}}

现在的问题是,上面的代码有什么问题?又该如何解决?

奇怪的是,在 Dart/Flutter 中使用 json 非常麻烦,因此非常感谢您的帮助。

【问题讨论】:

  • 这不是答案,而是建议:使用已经存在的 Json Serializable 包而不是手动解析 Json,也可以看到 freezed 也很好:pub.dev/packages/freezedpub.dev/packages/json_serializable
  • 感谢您的建议。我只是看了一下 json_serializable ,从描述中它似乎可以做到,但是你应该如何使用它呢?文档完全没有意义,所以我会坚持手动编码...

标签: json flutter dart


【解决方案1】:

您可以在下面复制粘贴运行完整代码
你可以看到MapTest类的完整代码

代码sn-p

String jsonString = '''
    {"coworkers": {"1":{"b":42,"s":"Astfgl"},"666":{"b":1234,"s":"Vassenego"}}}
    ''';

MapTest mapTest = mapTestFromJson(jsonString);

print(mapTest.coworkers["1"].b);
print(mapTest.coworkers["666"].s);

String str = mapTestToJson(mapTest);
print(str);

输出

I/flutter (26208): 42
I/flutter (26208): Vassenego
I/flutter (26208): {"coworkers":{"1":{"b":42,"s":"Astfgl"},"666":{"b":1234,"s":"Vassenego"}}}

完整代码

import 'package:flutter/material.dart';
import 'dart:convert';

MapTest mapTestFromJson(String str) => MapTest.fromJson(json.decode(str));

String mapTestToJson(MapTest data) => json.encode(data.toJson());

class MapTest {
  Map<String, Coworker> coworkers;

  MapTest({
    this.coworkers,
  });

  factory MapTest.fromJson(Map<String, dynamic> json) => MapTest(
        coworkers: Map.from(json["coworkers"])
            .map((k, v) => MapEntry<String, Coworker>(k, Coworker.fromJson(v))),
      );

  Map<String, dynamic> toJson() => {
        "coworkers": Map.from(coworkers)
            .map((k, v) => MapEntry<String, dynamic>(k, v.toJson())),
      };
}

class Coworker {
  int b;
  String s;

  Coworker({
    this.b,
    this.s,
  });

  factory Coworker.fromJson(Map<String, dynamic> json) => Coworker(
        b: json["b"],
        s: json["s"],
      );

  Map<String, dynamic> toJson() => {
        "b": b,
        "s": s,
      };
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    String jsonString = '''
    {"coworkers": {"1":{"b":42,"s":"Astfgl"},"666":{"b":1234,"s":"Vassenego"}}}
    ''';

    MapTest mapTest = mapTestFromJson(jsonString);

    print(mapTest.coworkers["1"].b);
    print(mapTest.coworkers["666"].s);

    String str = mapTestToJson(mapTest);
    print(str);

    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

【讨论】:

    【解决方案2】:

    只需更改您的 'coworkers':jsonEncode(_mapHell),

    '"coworkers"' : jsonEncode(_mapHell),
    

    例子

    class MapTest {
      Map<String, SimpleData> _mapHell = Map<String, SimpleData>();
    
      MapTest() {
        _mapHell['1'] = SimpleData(42, "Astfgl");
        _mapHell['666'] = SimpleData(1234, "Vassenego");
      }
    
      MapTest.fromJson(Map<String, dynamic> json) {
        _mapHell = jsonDecode(json['coworkers']);
      }
    
      Map<String, dynamic> toJson() => {
        '"coworkers"' : jsonEncode(_mapHell),
      };
    }
    

    【讨论】:

      猜你喜欢
      • 2021-09-05
      • 2020-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-24
      • 1970-01-01
      • 2014-08-27
      • 2017-01-02
      相关资源
      最近更新 更多