【问题标题】:How to decode from json in this situation?在这种情况下如何从 json 解码?
【发布时间】:2021-08-24 04:27:33
【问题描述】:

我将整个类保存为我的 Parse Back4App 服务器上的 json 对象。将对象解析为 json 很痛苦,因为我需要在嵌套类 Book 和主类 DatabaseSyncItem 中将许多属性转换为字符串。现在我不知道如何将这个 json 对象转回 DatabaseSyncObject。我假设将嵌套的 json book 对象返回到对象模型也是如此,也就是说它不会以这种方式工作。

我遇到错误并且没有成功。如果我尝试从 main 中的 json 对象列表访问特定索引,我可以到达某个地方,但这非常混乱。在这个情况下,你会怎么做?帮帮我,我第一次使用 json。

尝试应用这些帖子但没有工作:

import 'dart:convert';
import 'dart:io';
import 'package:hive/hive.dart';
import 'package:parse_server_sdk/parse_server_sdk.dart';
import 'package:service_database_sync/data/books_hardcoded.dart';
import 'package:service_database_sync/models/book_model.dart';
import 'package:service_database_sync/models/database_sync_model.dart';
import 'package:service_database_sync/services/demo_services.dart';
import 'package:service_database_sync/services/server_database_services.dart';

Future<void> main(List<String> arguments) async {
  Hive.init('hive_database');
  Hive.registerAdapter(BookAdapter());
  await Parse().initialize(
    ServerDatabaseServices().keyApplicationId,
    ServerDatabaseServices().keyParseServerUrl,
    clientKey: ServerDatabaseServices().keyClientKey,
    debug: true,
  );

  final test = updateLocalDatabase();
  Future<List> getList() {
    return Future.value(test);
  }

  var list = await getList();
  var jsonObject = list[2]['DatabaseSyncItem'];
  // var backToObject = jsonDecode(jsonObject); // error: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String'
  var backToObject = DatabaseSyncItem.fromJson(jsonObject); // error: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Book'
  print(backToObject);
}

// This method will get server database
  Future<List<ParseObject>> updateLocalDatabase() async {
    final events = QueryBuilder<ParseObject>(ParseObject('Event'));
    final apiResponse = await events.query();
    if (apiResponse.success && apiResponse.result != null) {
      return apiResponse.results;
    } else {
      return [];
    }
  }

part 'database_sync_model.g.dart';

@HiveType(typeId: 1)
class DatabaseSyncItem {
  @HiveField(0)
  Book previousBookValue;

  @HiveField(1)
  Book updatedBookValue;

  @HiveField(2)
  DateTime dateAdded;

  @HiveField(3)
  DateTime lastModified;

  @HiveField(4)
  DatabaseAction entryAction;

  DatabaseSyncItem({
    this.previousBookValue,
    this.updatedBookValue,
    this.dateAdded,
    this.lastModified,
    this.entryAction,
  });

  @override
  String toString() {
  return '''
  previousValue: $previousBookValue
  updatedValue: $updatedBookValue
  dateAdded: $dateAdded
  lastModified: $lastModified
  entryAction: $entryAction
  ''';
   }

  // Turn json back into data model
  DatabaseSyncItem.fromJson(Map<String, dynamic> json)
      : previousBookValue = json['previousBookValue'],
        updatedBookValue = json['updatedBookValue'],
        dateAdded = json['dateAdded'],
        lastModified = json['lastModified'],
        entryAction = json['entryAction'];

  // Turn data model into json
  Map<String, dynamic> toJson() => {
        'previousBookValue': previousBookValue,
        'updatedBookValue': updatedBookValue,
        'dateAdded': dateAdded,
        'lastModified': lastModified,
        'entryAction': entryAction.toString(),
      };
}

enum DatabaseAction {
  create,
  update,
  delete,
}

import 'package:hive/hive.dart';
part 'book_model.g.dart';

@HiveType(typeId: 0)
class Book {
  @HiveField(0)
  String title;

  @HiveField(1)
  String author;

  @HiveField(2)
  DateTime publishingDate;

  @HiveField(3)
  DateTime dateAdded;

  @HiveField(4)
  DateTime lastModified;

  Book({
    this.title,
    this.author,
    this.publishingDate,
    this.dateAdded,
    this.lastModified,
  });

  @override
  String toString() {
  return '''
  title: $title
  author: $author
  publishingDate: $publishingDate
  dateAdded: $dateAdded
  lastModified $lastModified
  ''';
   }

  Book.fromJson(Map<String, dynamic> json)
      : title = json['title'],
        author = json['author'],
        publishingDate = json['publishingDate'],
        dateAdded = json['dateAdded'],
        lastModified = json['lastModified'];

  Map<String, dynamic> toJson() => {
        'title': title,
        'author': author,
        'publishingDate': publishingDate.toIso8601String(),
        'dateAdded': dateAdded.toIso8601String(),
        'lastModified': lastModified.toIso8601String()
      };
}

【问题讨论】:

  • 您介意解释一下您想通过序列化/反序列化实现什么吗?为了更好地理解,您是在尝试序列化/反序列化一个类还是一个类的对象?
  • 是的,当然,我正在尝试序列化/反序列化一个类对象。这是一个演示项目,但我正在尝试创建服务器主数据库更改日志。所有授权用户将创建、更新和删除事件推送到服务器数据库。他们都会从这个数据库中读取数据,以了解如何更新他们的本地数据库。这将是具有历史记录和恢复能力的最后一次写入获胜类型的系统。感谢 Davi 的任何帮助,json 需要一些时间来适应。另外我想知道是否可以使用序列化程序包来处理这一切?
  • SDK 实现了 toJson (github.com/parse-community/Parse-SDK-Flutter/blob/master/…) 和 fromJosn (github.com/parse-community/Parse-SDK-Flutter/blob/master/…) 函数。尝试使用它们可能会更容易。

标签: json dart parse-platform back4app


【解决方案1】:

似乎这个答案比我最初预期的要复杂得多。需要使用json序列化包和json注解包。

这些包是必需的,当您查看生成的用于处理类型、null 以及嵌套类的代码时,您就会明白为什么。以防其他人遇到这种情况。

import 'package:hive/hive.dart';
import 'package:json_annotation/json_annotation.dart';
part 'book_model.g.dart';

@JsonSerializable(includeIfNull: true)
@HiveType(typeId: 0)
class Book {
  @HiveField(0)
  String title;

  @HiveField(1)
  String author;

  @HiveField(2)
  DateTime publishingDate;

  @HiveField(3)
  DateTime dateAdded;

  @HiveField(4)
  DateTime lastModified;

  Book({
    required this.title,
    required this.author,
    required this.publishingDate,
    required this.dateAdded,
    required this.lastModified,
  });

  factory Book.fromJson(Map<String, dynamic> json) => _$BookFromJson(json);
  Map<String, dynamic> toJson() => _$BookToJson(this);

  @override
  String toString() {
    return '''
  title: $title
  author: $author
  publishingDate: $publishingDate
  dateAdded: $dateAdded
  lastModified $lastModified
  ''';
  }
}

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'book_model.dart';

// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************

class BookAdapter extends TypeAdapter<Book> {
  @override
  final int typeId = 0;

  @override
  Book read(BinaryReader reader) {
    final numOfFields = reader.readByte();
    final fields = <int, dynamic>{
      for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
    };
    return Book(
      title: fields[0] as String,
      author: fields[1] as String,
      publishingDate: fields[2] as DateTime,
      dateAdded: fields[3] as DateTime,
      lastModified: fields[4] as DateTime,
    );
  }

  @override
  void write(BinaryWriter writer, Book obj) {
    writer
      ..writeByte(5)
      ..writeByte(0)
      ..write(obj.title)
      ..writeByte(1)
      ..write(obj.author)
      ..writeByte(2)
      ..write(obj.publishingDate)
      ..writeByte(3)
      ..write(obj.dateAdded)
      ..writeByte(4)
      ..write(obj.lastModified);
  }

  @override
  int get hashCode => typeId.hashCode;

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is BookAdapter &&
          runtimeType == other.runtimeType &&
          typeId == other.typeId;
}

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

Book _$BookFromJson(Map<String, dynamic> json) {
  return Book(
    title: json['title'] as String,
    author: json['author'] as String,
    publishingDate: DateTime.parse(json['publishingDate'] as String),
    dateAdded: DateTime.parse(json['dateAdded'] as String),
    lastModified: DateTime.parse(json['lastModified'] as String),
  );
}

Map<String, dynamic> _$BookToJson(Book instance) => <String, dynamic>{
      'title': instance.title,
      'author': instance.author,
      'publishingDate': instance.publishingDate.toIso8601String(),
      'dateAdded': instance.dateAdded.toIso8601String(),
      'lastModified': instance.lastModified.toIso8601String(),
    };
import 'package:json_annotation/json_annotation.dart';
import 'book_model.dart';
import 'package:hive/hive.dart';
part 'database_sync_model.g.dart';

@JsonSerializable(includeIfNull: true)
@HiveType(typeId: 1)
class DatabaseSyncItem {
  @HiveField(0)
  Book? previousBookValue;

  @HiveField(1)
  Book? updatedBookValue;

  @HiveField(2)
  DateTime dateAdded;

  @HiveField(3)
  DateTime lastModified;

  @HiveField(4)
  DatabaseAction entryAction;

  DatabaseSyncItem({
    this.previousBookValue,
    this.updatedBookValue,
    required this.dateAdded,
    required this.lastModified,
    required this.entryAction,
  });

  factory DatabaseSyncItem.fromJson(Map<String, dynamic> json) => _$DatabaseSyncItemFromJson(json);
  Map<String, dynamic> toJson() => _$DatabaseSyncItemToJson(this);

  @override
  String toString() {
  return '''
  previousValue: $previousBookValue
  updatedValue: $updatedBookValue
  dateAdded: $dateAdded
  lastModified: $lastModified
  entryAction: $entryAction
  ''';
   }
}

enum DatabaseAction {
  create,
  update,
  delete,
}

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'database_sync_model.dart';

// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************

class DatabaseSyncItemAdapter extends TypeAdapter<DatabaseSyncItem> {
  @override
  final int typeId = 1;

  @override
  DatabaseSyncItem read(BinaryReader reader) {
    final numOfFields = reader.readByte();
    final fields = <int, dynamic>{
      for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
    };
    return DatabaseSyncItem(
      previousBookValue: fields[0] as Book?,
      updatedBookValue: fields[1] as Book?,
      dateAdded: fields[2] as DateTime,
      lastModified: fields[3] as DateTime,
      entryAction: fields[4] as DatabaseAction,
    );
  }

  @override
  void write(BinaryWriter writer, DatabaseSyncItem obj) {
    writer
      ..writeByte(5)
      ..writeByte(0)
      ..write(obj.previousBookValue)
      ..writeByte(1)
      ..write(obj.updatedBookValue)
      ..writeByte(2)
      ..write(obj.dateAdded)
      ..writeByte(3)
      ..write(obj.lastModified)
      ..writeByte(4)
      ..write(obj.entryAction);
  }

  @override
  int get hashCode => typeId.hashCode;

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is DatabaseSyncItemAdapter &&
          runtimeType == other.runtimeType &&
          typeId == other.typeId;
}

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

DatabaseSyncItem _$DatabaseSyncItemFromJson(Map<String, dynamic> json) {
  return DatabaseSyncItem(
    previousBookValue: json['previousBookValue'] == null
        ? null
        : Book.fromJson(json['previousBookValue'] as Map<String, dynamic>),
    updatedBookValue: json['updatedBookValue'] == null
        ? null
        : Book.fromJson(json['updatedBookValue'] as Map<String, dynamic>),
    dateAdded: DateTime.parse(json['dateAdded'] as String),
    lastModified: DateTime.parse(json['lastModified'] as String),
    entryAction: _$enumDecode(_$DatabaseActionEnumMap, json['entryAction']),
  );
}

Map<String, dynamic> _$DatabaseSyncItemToJson(DatabaseSyncItem instance) =>
    <String, dynamic>{
      'previousBookValue': instance.previousBookValue,
      'updatedBookValue': instance.updatedBookValue,
      'dateAdded': instance.dateAdded.toIso8601String(),
      'lastModified': instance.lastModified.toIso8601String(),
      'entryAction': _$DatabaseActionEnumMap[instance.entryAction],
    };

K _$enumDecode<K, V>(
  Map<K, V> enumValues,
  Object? source, {
  K? unknownValue,
}) {
  if (source == null) {
    throw ArgumentError(
      'A value must be provided. Supported values: '
      '${enumValues.values.join(', ')}',
    );
  }

  return enumValues.entries.singleWhere(
    (e) => e.value == source,
    orElse: () {
      if (unknownValue == null) {
        throw ArgumentError(
          '`$source` is not one of the supported values: '
          '${enumValues.values.join(', ')}',
        );
      }
      return MapEntry(unknownValue, enumValues.values.first);
    },
  ).key;
}

const _$DatabaseActionEnumMap = {
  DatabaseAction.create: 'create',
  DatabaseAction.update: 'update',
  DatabaseAction.delete: 'delete',
};

【讨论】:

    猜你喜欢
    • 2022-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-04
    • 1970-01-01
    • 2016-04-24
    • 2017-04-29
    相关资源
    最近更新 更多