Json in Dart

import 'dart:convert';
import 'dart:io';

// We'll use these two classes to demonstrate encoding and
// decoding of custom types below.
class Response1 {
  int page;
  List<String> fruits;

  Response1(this.page, this.fruits);
}

// Only fields with non-null values will be encoded/decoded in JSON.
class Response2 {
  int? page;
  List<String>? fruits;

  Response2({this.page, this.fruits});

  Map<String, dynamic> toJson() => {
        'page': page,
        'fruits': fruits,
      };

  factory Response2.fromJson(Map<String, dynamic> json) {
    return Response2(
      page: json['page'],
      fruits: List<String>.from(json['fruits']),
    );
  }
}

void main() {
  // First we'll look at encoding basic data types to
  // JSON strings. Here are some examples for atomic
  // values.
  print(jsonEncode(true));

  print(jsonEncode(1));

  print(jsonEncode(2.34));

  print(jsonEncode("gopher"));

  // And here are some for lists and maps, which encode
  // to JSON arrays and objects as you'd expect.
  var slcD = ["apple", "peach", "pear"];
  print(jsonEncode(slcD));

  var mapD = {"apple": 5, "lettuce": 7};
  print(jsonEncode(mapD));

  // The JSON package can automatically encode your
  // custom data types. It will only include non-null
  // fields in the encoded output.
  var res1D = Response1(1, ["apple", "peach", "pear"]);
  print(jsonEncode(res1D));

  var res2D = Response2(page: 1, fruits: ["apple", "peach", "pear"]);
  print(jsonEncode(res2D));

  // Now let's look at decoding JSON data into Dart
  // values. Here's an example for a generic data
  // structure.
  var byt = '{"num":6.13,"strs":["a","b"]}';

  // We need to provide a variable where the JSON
  // package can put the decoded data. This
  // Map<String, dynamic> will hold a map of strings
  // to dynamic types.
  Map<String, dynamic> dat = jsonDecode(byt);
  print(dat);

  // We can access values in the decoded map directly.
  var num = dat['num'];
  print(num);

  // Accessing nested data is straightforward.
  var strs = dat['strs'] as List;
  var str1 = strs[0];
  print(str1);

  // We can also decode JSON into custom data types.
  // This has the advantages of adding additional
  // type-safety to our programs.
  var str = '{"page": 1, "fruits": ["apple", "peach"]}';
  var res = Response2.fromJson(jsonDecode(str));
  print(res.page);
  print(res.fruits?[0]);

  // In the examples above we always used strings as
  // intermediates between the data and JSON representation.
  // We can also stream JSON encodings directly to stdout.
  var encoder = JsonEncoder.withIndent('  ');
  var d = {"apple": 5, "lettuce": 7};
  print(encoder.convert(d));
}

This Dart code demonstrates JSON encoding and decoding, covering the same concepts as the original Go example. Here’s a brief explanation of the changes and Dart-specific features:

  1. We use dart:convert for JSON operations and dart:io for stdout.

  2. Classes are used instead of structs. We define toJson() and fromJson() methods for custom encoding/decoding.

  3. Dart uses ? for nullable types and late for non-nullable types that are initialized after declaration.

  4. jsonEncode() and jsonDecode() are used for JSON operations instead of Marshal() and Unmarshal().

  5. Dart uses Map<String, dynamic> for JSON objects instead of map[string]interface{}.

  6. Type casting in Dart is done with as keyword.

  7. Dart doesn’t have a direct equivalent to Go’s NewEncoder(). Instead, we use JsonEncoder for pretty-printing JSON.

To run this Dart program, save it as json_example.dart and use the dart command:

$ dart run json_example.dart

This will output the results of various JSON encoding and decoding operations, similar to the Go example.