Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Samples to compare using fromJson/toJson and using data objects provided by the attributes package #15

Closed
navispatial opened this issue Oct 2, 2021 · 1 comment
Labels
documentation Improvements or additions to documentation 🗒️ attributes Related to the code package "attributes"

Comments

@navispatial
Copy link
Member

See sample for previous version Add new sample with domain model classes and JSON serialization #10.

These samples included in the release version 0.8.0.

A sample using attributes package

import 'package:attributes/data.dart';

void main() {
  _decodeSampleData();
}

/// [Address] model with [street] and [city] fields.
///
/// Sample source data as a JSON Object:
/// `{ "street": "Main street", "city": "Anytown" }`
class Address {
  final String street;
  final String city;

  const Address({required this.street, required this.city});

  static Address fromData(DataObject data) => Address(
        street: data.getString('street'),
        city: data.getString('city'),
      );

  DataObject toData() => DataObject.of({
        'street': street,
        'city': city,
      });
}

/// [Person] with [name], [age], an optional [length] and aggregated [address].
///
/// Sample source data as a JSON Object:
/// ```json
///   {
///     "name": "John Doe",
///     "age": 52,
///     "length": 1.75,
///     "address": { "street": "Main street", "city": "Anytown" },
///     "updated": "2021-08-09 09:00Z"
///   }
/// ```
class Person {
  final String name;
  final int age;
  final double? length;
  final Address address;
  final DateTime updatedUTC;

  const Person(
      {required this.name,
      required this.age,
      this.length,
      required this.address,
      required this.updatedUTC});

  static Person fromData(DataObject data) => Person(
      name: data.getString('name'),
      age: data.getInt('age'),
      length: data.tryDouble('length'),
      address: Address.fromData(data.object('address')),
      updatedUTC: data.getTimeUTC('updated'));

  DataObject toData() => DataObject.of({
        'name': name,
        'age': age,
        if (length != null) 'length': length,
        'address': address.toData(),
        'updated': updatedUTC,
      });
}

/// [PersonCollection] model with a list of [Person] model objects.
///
/// Sample source data as a JSON Array:
/// ```json
///   [
///     {
///       "name": "John Doe",
///       "age": 52,
///       "length": 1.75,
///       "address": { "street": "Main street", "city": "Anytown" },
///       "updated": "2021-08-09 09:00Z"
///     }
///   ]
/// ```
class PersonCollection {
  final Iterable<Person> persons;

  const PersonCollection({required this.persons});

  static PersonCollection fromData(DataArray data) =>
      PersonCollection(persons: data.objectsToList(Person.fromData));

  DataArray toData() =>
      DataArray.from<Person>(persons, (person) => person.toData());
}

void _decodeSampleData() {
  // Some json data as JSON Array.
  const jsonData = '''
  [
     { 
       "name": "John Doe",
       "age": 52,
       "length": 1.75,
       "address": { "street": "Main street", "city": "Anytown" },
       "updated": "2021-08-09 09:00Z"
     }
  ]
  ''';

  // Decode JSON using DataArray.
  final decoded = DataArray.decodeJson(jsonData);

  // Map decoded objects to the domain model objects.
  final personCollection = PersonCollection.fromData(decoded);

  // Use domain objects, here just print names and address info.
  for (final person in personCollection.persons) {
    print('${person.name} lives in ${person.address.street}');
  }

  // JSON data encoded from domain objects and outputted
  print(personCollection.toData().encodeJson());
}

A sample NOT using attributes package

import 'dart:convert';

void main() {
  _decodeSampleData();
}

/// [Address] model with [street] and [city] fields.
///
/// Sample source data as a JSON Object:
/// `{ "street": "Main street", "city": "Anytown" }`
class Address {
  final String street;
  final String city;

  const Address({required this.street, required this.city});

  static Address fromJson(Map<String, dynamic> json) => Address(
        street: json['street'] as String,
        city: json['city'] as String,
      );

  Map<String, dynamic> toJson() => <String, dynamic>{
        'street': street,
        'city': city,
      };
}

/// [Person] with [name], [age], an optional [length] and aggregated [address].
///
/// Sample source data as a JSON Object:
/// ```json
///   {
///     "name": "John Doe",
///     "age": 52,
///     "length": 1.75,
///     "address": { "street": "Main street", "city": "Anytown" },
///     "updated": "2021-08-09 09:00Z"
///   }
/// ```
class Person {
  final String name;
  final int age;
  final double? length;
  final Address address;
  final DateTime updatedUTC;

  const Person(
      {required this.name,
      required this.age,
      this.length,
      required this.address,
      required this.updatedUTC});

  static Person fromJson(Map<String, dynamic> json) => Person(
      name: json['name'] as String,
      age: json['age'] as int,
      length: json['length'] as double?,
      address: Address.fromJson(json['address'] as Map<String, dynamic>),
      updatedUTC: DateTime.parse(json['updated'] as String).toUtc());

  Map<String, dynamic> toJson() => <String, dynamic>{
        'name': name,
        'age': age,
        if (length != null) 'length': length,
        'address': address.toJson(),
        'updated': updatedUTC.toIso8601String(),
      };
}

/// [PersonCollection] model with a list of [Person] model objects.
///
/// Sample source data as a JSON Array:
/// ```json
///   [
///     {
///       "name": "John Doe",
///       "age": 52,
///       "length": 1.75,
///       "address": { "street": "Main street", "city": "Anytown" },
///       "updated": "2021-08-09 09:00Z"
///     }
///   ]
/// ```
class PersonCollection {
  final Iterable<Person> persons;

  const PersonCollection({required this.persons});

  static PersonCollection fromJson(Iterable<dynamic> json) => PersonCollection(
        persons: json
            .map<Person>((dynamic element) =>
                Person.fromJson(element as Map<String, dynamic>))
            .toList(growable: false),
      );

  List<dynamic> toJson() => persons
      .map<Map<String, dynamic>>((person) => person.toJson())
      .toList(growable: false);
}

void _decodeSampleData() {
  // Some json data as JSON Array.
  const jsonData = '''
  [
     { 
       "name": "John Doe",
       "age": 52,
       "length": 1.75,
       "address": { "street": "Main street", "city": "Anytown" },
       "updated": "2021-08-09 09:00Z"
     }
  ]
  ''';

  // Decode JSON and cast it to `Iterable<Object?>`.
  final decoded = json.decode(jsonData) as Iterable<dynamic>;

  // Map decoded objects to the domain model objects.
  final personCollection = PersonCollection.fromJson(decoded);

  // Use domain objects, here just print names and address info.
  for (final person in personCollection.persons) {
    print('${person.name} lives in ${person.address.street}');
  }

  // JSON data encoded from domain objects and outputted
  print(json.encode(personCollection.toJson()));
}
@navispatial navispatial added documentation Improvements or additions to documentation 🗒️ attributes Related to the code package "attributes" labels Oct 2, 2021
@navispatial
Copy link
Member Author

Implemented in Release version 0.8.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation 🗒️ attributes Related to the code package "attributes"
Projects
None yet
Development

No branches or pull requests

1 participant