JSON_serialIZABLE

1. The integrated json_serializable

Pubspec.yaml adds the following dependencies

Json_annotation: ^2.0.0 dev_dependencies: build_runner: ^1.0.0 jSON_serialIZABLE: ^2.0.0Copy the code

Remember to execute flutter Packages get after adding

2. To create a Model

Add your JSON data here (click me) to generate a model file as follows:

  1. Fill in the JSON data
  2. Fill in the name of the class
  3. Copy or download

3. Generate files

Xxx.g.art can be generated by executing flutter Packages pub run build_runner watch in the project root directory

4. Parsing and serialization

Import ‘dart:convert’;

///json to model String jsonString ='{"name": "Tony","email": "[email protected]"}'Map userMap = json.decode(jsonString); var user = User.fromJson(userMap); String jsonEncode = json.encode(user);print(jsonEncode);
Copy the code

Second, automatic template generation

The above process requires converting the JSON generated site to the Model each time, and then we will directly generate the site locally, just need to write a user. Json file and execute the command. In this way, you can directly modify the JSON file after each modification of the JSON structure and run the command. In addition, the JSON structure can be stored locally for easy viewing.

1. Use json_model

Integrated json_model

Dev_dependencies: json_model: ^ hundreds# Latest version
Copy the code

use

  1. Create a directory named “jsons” in the project root directory.
  2. Create/copy Json file to “jsons” directory
  3. Run pub run json_model or flutter packages pub run json_model to generate the Dart model class. The generated files default to the “lib/models” directory

Specific document address: github.com/flutterchin…

2. A little optimization

The above method is convenient enough to import the plug-in package directly, but there are a few problems in using the process:

  • The generated Model file name is the same as the JSON file name, if the file name is underlined_The generated class name is also underlined, but I prefer to use the camel name
  • As above, when the field name has an underscore_, the generated field is also underlined, to use the camel name must be manually added above the field@JsonKey(name: 'user_name')
  • Automatic resolution of data types is supported onlybool num Map ListAnd so on several common types, if yesDateTimeFields of type or other types can only be resolved to String.
  • The resulting model was not perfectly formatted, and obsessive users had to manually format it again

If you feel this is unfriendly or have writing habits then do it yourself. I’ve changed it in my own way:

  • Class name, field name camel name
  • supportDateTimeType (additional support can be added later)
  • Perfect formatting

How to do it: Do it yourself, without using jSON_model

  1. Create a directory named “jsons” in the project root directory.
  2. Create/copy Json file to “jsons” directory
  3. Create in the project root directorymo.dartFile, as follows:
import 'dart:convert';
import 'dart:io';
import 'package:path/path.dart' as path;

const TAG = "\ $";
const SRC = "./json"; //JSON directory const DIST ="lib/models/"; // Output the model directory voidwalkVar SRC = new Directory(SRC); var list = src.listSync(); var template ="import 'package:json_annotation/json_annotation.dart'; \r\n%t\npart '%s.g.dart'; \r\n\r\n@JsonSerializable()\r\nclass %s {\r\n %s(); \r\n\r\n %sfactory %s.fromJson(Map
      
        json) => _\$%sFromJson(json); \r\n\r\n Map
       
         toJson() => _\$%sToJson(this); \r\n}\r\n"
       ,>
      ,>;
  File file;
  list.forEach((f) {
    if (FileSystemEntity.isFileSync(f.path)) {
      file = new File(f.path);
      var paths = path.basename(f.path).split(".");
      String name = paths.first;
      if(paths.last.toLowerCase() ! ="json" || name.startsWith("_")) return;
      if (name.startsWith("_")) return; Var map = json.decode(file.readasstringsync ()); // To avoid importing the same package repeatedly, we use Set to save the generated import statements. varset = new Set<String>();
      StringBuffer attrs = new StringBuffer();
      (map as Map<String, dynamic>).forEach((key, v) {
        if (key.startsWith("_")) return;
        /// # # # # # # # # # # # # # # # # # # # # # # # # # # # # #/// Process key contains"_", and add @jsonKey (name="key")
        if (key.contains("_")) {
          attrs.write('@JsonKey(name: "$key")');
          attrs.write("\r\n ");
          attrs.write(getType(v, set, name));
          attrs.write("");
          attrs.write(changeToCamelCase(key, false));
          attrs.writeln(";");
          attrs.write("\r\n ");
        } else {
          attrs.write(getType(v, set, name));
          attrs.write("");
          attrs.write(key);
          attrs.writeln(";");
          attrs.write("\r\n "); }}); String className ="";
      /// # # # # # # # # # # # # # # # # # # # # # # # # # # # # #/ / / processing"_"When class is not hump namingif (name.contains("_")) {
        className = changeToCamelCase(name, true);
      } else {
        className = name[0].toUpperCase() + name.substring(1);
      }
      var dist = format(template, [
        name,
        className,
        className,
        attrs.toString(),
        className,
        className,
        className
      ]);
      var _import = set.join("; \r\n");
      _import += _import.isEmpty ? "" : ";";
      dist = dist.replaceFirst("%t", _import); // Print new File("$DIST$name.dart").writeAsStringSync(dist); }}); } / / /# # # # # # # # # # # # # # # # # # # # # # # # # # # # #String changeToCamelCase(String word, bool big) {if (word.contains("_")) {
    String result = "";
    List<String> words = word.split("_");
    for (var value in words) {
      result += (value[0].toUpperCase() + value.substring(1).toLowerCase());
    }
    return big ? result : (result[0].toLowerCase() + result.substring(1));
  } else {
    return big
        ? word[0].toUpperCase() + word.substring(1)
        : word[0].toLowerCase() + word.substring(1);
  }
}

String changeFirstChar(String str, [bool upper = true]) {
  return(upper ? str[0].toUpperCase() : str[0].toLowerCase()) + str.substring(1); String getType(v, Set<String>);set, String current) {
  current = current.toLowerCase();
  if (v is bool) {
    return "bool";
  } else if (v is num) {
    return "num";
  } else if (v is Map) {
    return "Map<String,dynamic>";
  } else if (v is List) {
    return "List";
  } else if (v is String) {
    /// # # # # # # # # # # # # # # # # # # # # # # # # # # # # #Parse (v); parse(v); // Add DateTime.if(dateTime ! = null) {return "DateTime"; }} catch (e) {} // Handle special flagsif (v.startsWith("$TAG[]")) {
      var className = changeFirstChar(v.substring(3), false);
      if(className.toLowerCase() ! = current) { set.add('import "$className.dart"'); } / / /# # # # # # # # # # # # # # # # # # # # # # # # # # # # #/// Custom model type name big hump namereturn "List<${changeToCamelCase(className, true)}>";
    } else if (v.startsWith(TAG)) {
      var fileName = changeFirstChar(v.substring(1), false);
      if(fileName.toLowerCase() ! = current) { set.add('import "$fileName.dart"'); } / / /# # # # # # # # # # # # # # # # # # # # # # # # # # # # #/// Custom model type name big hump namereturn changeToCamelCase(fileName, true);
    }
    return "String";
  } else {
    return "String"; String format(String FMT, List<Object> params) {int matchIndex = 0; String replace(Match m) {if (matchIndex < params.length) {
      switch (m[0]) {
        case "%s":
          returnparams[matchIndex++].toString(); }}else {
      throw new Exception("Missing parameter for string format");
    }
    throw new Exception("Invalid format string: " + m[0].toString());
  }

  return fmt.replaceAllMapped("%s", replace);
}

void main() {
  walk();
}
Copy the code

Here is to generate the model method and template, Json_model’s predecessor, from here Annotations include “# # # # # # # # # # # # # # # # # # # # # # # # # # # # #” where is the place where the modified, everyone have their own needs to be modified.

  1. Create in the project root directorymo.shFile, as follows:
#! /usr/bin/env bash
dart mo.dart
flutter packages pub run build_runner build --delete-conflicting-outputs
Copy the code

This is a script that packages commands and executes them together

Note: If you have not configured the DART environment variable, you will: (under Mac)

  • vim ~/.bash_profile
  • addexport PATH=your flutter path/flutter/bin/cache/dart-sdk/bin:$PATH
  • source ~/.bash_profile
  • dart --versionDisplay the version number normally
  1. After all the above configurations are complete, only one step is required to execute the project root directorysh mo.shOk, everything worked out perfectly. Let me show you the results

Important reference: www.jianshu.com/p/421053612…

Book. Flutterchina. Club/chapter10 / j…