【flutter大杂烩】记一次json解析类型转换异常

2,144 阅读1分钟

如果您觉得文章对您有帮助,欢迎 👍, 我的 Github.


调试josn bean序列化时,发现下面这个错误:

════════ Exception caught by gesture ═══════════════════════
The following _CastError was thrown while handling a gesture:
type 'String' is not a subtype of type 'int' in type cast

When the exception was thrown, this was the stack: 
#0      _$DemoBeanFromJson (package:zmusic/test.g.dart:11:35)
#1      new DemoBean.fromJson (package:zmusic/test.dart:13:7)
#2      _MyHomePageState.build.<anonymous closure> (package:zmusic/main.dart:36:20)
#3      _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:772:19)
#4      _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:855:36)
...

使用的是json_serializable序列化json, 写了个demo复现了下:

test:

DemoBean.fromJson(jsonDecode('{"intField":"123","stringField":"123"}'));
import 'package:json_annotation/json_annotation.dart';

part 'test.g.dart';

@JsonSerializable()
class DemoBean {
  int intField;
  String stringField;

  DemoBean();

  factory DemoBean.fromJson(Map<String, dynamic> json) =>
      _$DemoBeanFromJson(json);

  Map<String, dynamic> toJson() => _$DemoBeanToJson(this);
}

.g.dart:

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'test.dart';

// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************

DemoBean _$DemoBeanFromJson(Map<String, dynamic> json) {
  return DemoBean()
    ..intField = json['intField'] as int //问题出在这里,json中是真实的数据类型,as时导致了crash
    ..stringField = json['stringField'] as String;//问题出在这里,json中是真实的数据类型,as时导致了crash
}

Map<String, dynamic> _$DemoBeanToJson(DemoBean instance) => <String, dynamic>{
      'intField': instance.intField,
      'stringField': instance.stringField,
    };

问题出在 json['intField'] as int ,json中是真实的数据类型,as时导致了crash.

查了下文档,发现可以使用 @JsonKey(fromJson: xxx) 的fromJson参数对转换过程做hook。 调整bean代码:

import 'package:json_annotation/json_annotation.dart';

part 'test.g.dart';

@JsonSerializable()
class DemoBean {
  @JsonKey(fromJson: _dynamicToInt)
  int intField;
  @JsonKey(fromJson: _dynamicToString)
  String stringField;

  DemoBean();

  factory DemoBean.fromJson(Map<String, dynamic> json) =>
      _$DemoBeanFromJson(json);

  Map<String, dynamic> toJson() => _$DemoBeanToJson(this);

  static _dynamicToInt(dynamic value) {
    return value == null ? null : int.parse(value);
  }

  static _dynamicToString(dynamic value) {
    return value == null ? null : value.toString();
  }
}

.g.dart

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'test.dart';

// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************

DemoBean _$DemoBeanFromJson(Map<String, dynamic> json) {
  return DemoBean()
    ..intField = DemoBean._dynamicToInt(json['intField'])
    ..stringField = DemoBean._dynamicToString(json['stringField']);
}

Map<String, dynamic> _$DemoBeanToJson(DemoBean instance) => <String, dynamic>{
      'intField': instance.intField,
      'stringField': instance.stringField,
    };

DemoBean._dynamicToInt(json['intField']) 没有as逻辑,问题解决。