<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: yangfanzn</title>
    <description>The latest articles on DEV Community by yangfanzn (@yangfanzn).</description>
    <link>https://dev.to/yangfanzn</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2879503%2F9673ea87-e557-4eb2-9279-795c5a07bda0.jpg</url>
      <title>DEV Community: yangfanzn</title>
      <link>https://dev.to/yangfanzn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yangfanzn"/>
    <language>en</language>
    <item>
      <title>How to Generate Code for Flutter?</title>
      <dc:creator>yangfanzn</dc:creator>
      <pubDate>Wed, 19 Feb 2025 15:44:43 +0000</pubDate>
      <link>https://dev.to/yangfanzn/how-to-generate-code-for-flutter-44kc</link>
      <guid>https://dev.to/yangfanzn/how-to-generate-code-for-flutter-44kc</guid>
      <description>&lt;p&gt;Hello everyone. I have developed a command‐line tool using TypeScript that offers the following features:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Generates class code from &lt;code&gt;JSON&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The generated classes support both serialization and deserialization.&lt;/li&gt;
&lt;li&gt;Works with all valid &lt;code&gt;JSON&lt;/code&gt; data formats.&lt;/li&gt;
&lt;li&gt;Supports &lt;code&gt;JSON&lt;/code&gt; as well as &lt;code&gt;JSON5&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Uses the &lt;code&gt;ref&lt;/code&gt; syntax to reference predefined structures, enabling the creation of recursive types.&lt;/li&gt;
&lt;li&gt;Currently, supports the &lt;code&gt;dart&lt;/code&gt; and &lt;code&gt;arkTs&lt;/code&gt; languages, with plans to support others in the future.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Tool Links &lt;a id="doc"&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/yangfanzn/json2any/tree/main/packages/json2class" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pub.dev/packages/json2class" rel="noopener noreferrer"&gt;Dart pub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/json2class" rel="noopener noreferrer"&gt;Node npm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ohpm.openharmony.cn/#/cn/detail/json2class" rel="noopener noreferrer"&gt;Openharmony ohpm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Develop This Tool
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;When I first started developing with Flutter, I found the official &lt;code&gt;json_serializable&lt;/code&gt; approach to be somewhat cumbersome, it required defining a lot of boilerplate and ensuring that properties matched specific conventions. When combined with HTTP requests, the amount of manual template code increases even further.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In my view, naming types can be a painful process. Even if you are working on a project by yourself, it is challenging to maintain a consistent naming convention from start to finish. In a team setting, even basic camelCase naming might not be reliably enforced. Ultimately, the specific name of a class is not critical; what matters is that the naming is completely consistent and easily identifiable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In any strongly typed language, to ensure type safety when working with dynamic data, you must predefine class types and implement serialization/deserialization. Although different languages handle this in various ways, the underlying structure of classes and the logic for serialization/deserialization are fundamentally similar.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Examples
&lt;/h2&gt;

&lt;p&gt;Below, I will demonstrate how to use this tool. As this is my first open source project, there might be aspects I haven’t fully considered yet—your feedback and suggestions are most welcome.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting Started
&lt;/h3&gt;

&lt;p&gt;Since this is a command‐line tool, you start from the terminal. I’ll begin by using &lt;code&gt;npx&lt;/code&gt;; other execution methods are similar. Detailed usage instructions can be found in the documentation at the Tool Links.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx json2class build &lt;span class="nt"&gt;-l&lt;/span&gt; dart@3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-l&lt;/code&gt; flag is shorthand for &lt;code&gt;--language&lt;/code&gt; and is used to specify the target language. Currently, it supports &lt;code&gt;dart@3&lt;/code&gt; and &lt;code&gt;arkTs@12&lt;/code&gt; with the number following &lt;code&gt;@&lt;/code&gt; representing the version.&lt;/p&gt;

&lt;p&gt;When you run this command, it will, by default,search for all &lt;code&gt;.json&lt;/code&gt; and &lt;code&gt;.json5&lt;/code&gt; files in the current directory (including subdirectories up to three levels deep).&lt;/p&gt;

&lt;p&gt;If everything is correct, the tool will generate a code file in the current directory.For &lt;code&gt;Dart&lt;/code&gt;, it will create &lt;code&gt;json2class.dart&lt;/code&gt;; for &lt;code&gt;arkTs&lt;/code&gt;, it will create &lt;code&gt;json2class.ets&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can specify a directory to search for &lt;code&gt;.json&lt;/code&gt; or &lt;code&gt;.json5&lt;/code&gt; files &lt;br&gt;
using the &lt;code&gt;-s&lt;/code&gt; or &lt;code&gt;--search&lt;/code&gt; flag (both absolute and relative paths are supported).&lt;/p&gt;

&lt;p&gt;You can specify an output directory using the &lt;code&gt;-o&lt;/code&gt; or &lt;code&gt;--output&lt;/code&gt; flag.&lt;/p&gt;

&lt;p&gt;It is recommended to add the generated file &lt;code&gt;json2class.*&lt;/code&gt; to your git ignore list.&lt;/p&gt;
&lt;h3&gt;
  
  
  Configuring JSON
&lt;/h3&gt;

&lt;p&gt;As long as your JSON is valid and constitutes an effective configuration,&lt;br&gt;
code generation will work smoothly.&lt;/p&gt;
&lt;h4&gt;
  
  
  1. A Simple Example
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Filename:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;test.json&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;a:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;b:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bbb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;c:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;o:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;o&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;o&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'ooo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;o&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The generated &lt;code&gt;Dart&lt;/code&gt; code will roughly look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;test&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;num&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;testo&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;testo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;testo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;num&lt;/span&gt; &lt;span class="n"&gt;o1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;o2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;o3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Indeed, I use a combination of the &lt;code&gt;filename&lt;/code&gt; and &lt;code&gt;the property name&lt;/code&gt; to form the class name. This method not only ensures consistent naming throughout but also retains clear identifiable.&lt;/p&gt;

&lt;p&gt;From the generated code, you can see the relationship between the property types/default values and the original JSON. If you prefer not to set default values, please refer to the documentation at the Tool Links for further details.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. How to Create Recursive Types?
&lt;/h4&gt;

&lt;p&gt;As mentioned earlier, while valid JSON can be processed without errors, it does not always guarantee that the desired type structure will be generated.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;test&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;num&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;testo&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;testo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;testo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;num&lt;/span&gt; &lt;span class="n"&gt;o1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;o2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;o3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;testo&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Recursive type&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a recursive type like the one above, plain JSON cannot fully describe it. We need to adopt a special syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;test.json&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;a:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;b:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'abc'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;c:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;o:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;o&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;o&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'ooo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;o&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;child:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$meta:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ref:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'/test#/o'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;ref&lt;/code&gt; reference is split into two parts by the &lt;code&gt;#&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/test&lt;/code&gt; is the filename. This can be any file within your JSON search directory,&lt;br&gt;
even if the file resides in a subdirectory (in which case, include the folder hierarchy).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/o&lt;/code&gt; specifies the field whose type you wish to reference; in this example, it is &lt;code&gt;testo&lt;/code&gt;.&lt;br&gt;
If the referenced type is in the current file, you can omit the filename and simply write &lt;code&gt;{ ref: '#/o' }&lt;/code&gt;. (Note that the # is mandatory.)&lt;/p&gt;

&lt;p&gt;Currently, under &lt;code&gt;$meta&lt;/code&gt;, only the &lt;code&gt;ref&lt;/code&gt; configuration is supported. &lt;br&gt;
If you have suggestions for additional features, please let me know,&lt;br&gt;
future updates might incorporate more options under &lt;code&gt;$meta&lt;/code&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  3. How to Handle Conflicts and Special Characters?
&lt;/h4&gt;

&lt;p&gt;Since &lt;code&gt;class names&lt;/code&gt; are generated by concatenating the &lt;code&gt;filename&lt;/code&gt; and the &lt;code&gt;property name&lt;/code&gt;, there may be extreme cases where type conflicts occur. In such instances, the command‐line tool will prompt you, and simply renaming the file will resolve the conflict.&lt;/p&gt;

&lt;p&gt;Renaming the file results in a new class name. Once again, the exact name of the class isn’t critical—the important factors are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The consistency of the class name generation rule.&lt;/li&gt;
&lt;li&gt;The identifiable of the class names.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a field contains special characters that are reserved keywords in the target language, the tool will automatically convert them using a specific algorithm. This conversion does not affect property usage or the serialized field names.&lt;/p&gt;
&lt;h3&gt;
  
  
  How to Use the Generated Code
&lt;/h3&gt;
&lt;h4&gt;
  
  
  1. Serialization and Deserialization
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'json2class.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;testo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fromJson&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;"o1"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"o2"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'ooo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"o3"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toJson&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The core functionality of the generated code is serialization and deserialization:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;fromJson&lt;/code&gt;: Deserializes JSON data.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;toJson&lt;/code&gt;: Serializes the object to JSON.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For convenience in converting JSON data from a string format, a method named fromAny is also provided. It accepts any input, attempts to convert it into a Map, and then calls fromJson to perform deserialization.&lt;/p&gt;

&lt;p&gt;For complete documentation on using the generated code, please refer to the Tool Links. We won’t elaborate further here.&lt;/p&gt;
&lt;h4&gt;
  
  
  2. Constructing Mock Data
&lt;/h4&gt;

&lt;p&gt;It is foreseeable that the ideal use case for the generated code is when retrieving data from a network. When the backend is not yet ready for integration testing, you might need to construct &lt;code&gt;mock&lt;/code&gt; data for development. Once you receive the API response schema from the backend, you can simultaneously configure &lt;code&gt;mock&lt;/code&gt; data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;test.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"statusCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"statusMessage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"userName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"json2class"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"userPhone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"13888888888"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"userAvator"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://xxx.yyy.com/avator.png"&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;testresult&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fromPreset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By using the &lt;code&gt;fromPreset&lt;/code&gt; method, the data configured in the JSON is populated into the object, allowing you to proceed with business logic. When the backend is ready for integration, simply replace &lt;code&gt;fromPreset&lt;/code&gt; with the actual API call. Of course, you could also encapsulate this further, using generics to provide a unified API interface and enabling one, click switching for &lt;code&gt;mock&lt;/code&gt; data with a single parameter.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Filling Rules
&lt;/h4&gt;

&lt;p&gt;Why were &lt;code&gt;filling rules&lt;/code&gt; designed? In frontend backend interactions, to ensure robust code, no backend data should be blindly trusted. &lt;br&gt;
This is why we deserialize and type-check the JSON data received from the backend.&lt;/p&gt;

&lt;p&gt;In real world scenarios, if the API response structure or types do not match our definitions, what should be done? Should an error be thrown? That would not be acceptable. When there is a discrepancy in structure or type, filling in with null might work, or assigning a default value for that type might be preferable. To accommodate different needs, &lt;code&gt;filling rules&lt;/code&gt; were designed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For Object Keys&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are essentially three cases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The field exists in both the input and the definition, and the types match perfectly. This is the ideal scenario—simply assign the value.&lt;/li&gt;
&lt;li&gt;The field exists in both, but the types do not match. In this case, the &lt;code&gt;DiffType&lt;/code&gt; enumeration determines how to fill the value.&lt;/li&gt;
&lt;li&gt;The field is missing in the input. Here, the &lt;code&gt;MissKey&lt;/code&gt; enumeration is used to decide how to fill it.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;For Arrays of Equal Length&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is straightforward: if the input array and the defined array have the same length, each element is filled based on its position. &lt;br&gt;
If a type mismatch occurs at a particular position, it is handled according to &lt;code&gt;DiffType&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For Arrays of Unequal Length&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For extra elements when the array lengths differ, the following rules apply:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enumeration &lt;code&gt;MoreIndex&lt;/code&gt;: When the input array length is greater than the defined array.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Enumeration&lt;/th&gt;
&lt;th&gt;Effect&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Fill&lt;/td&gt;
&lt;td&gt;Inserts the input value; if there is a type mismatch, sets a &lt;code&gt;default&lt;/code&gt; value or &lt;code&gt;null&lt;/code&gt; based on whether the field is optional&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Drop&lt;/td&gt;
&lt;td&gt;Discards the extra input data so that the array length matches the defined array&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Null&lt;/td&gt;
&lt;td&gt;Fills the extra elements with &lt;code&gt;null&lt;/code&gt; (for non-optional fields, &lt;code&gt;Null&lt;/code&gt; behaves the same as &lt;code&gt;Fill&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Enumeration &lt;code&gt;MissIndex&lt;/code&gt;: When the input array length is less than the defined array.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Enumeration&lt;/th&gt;
&lt;th&gt;Effect&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Fill&lt;/td&gt;
&lt;td&gt;Fills with default values; for multidimensional arrays, the filling is performed recursively&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Drop&lt;/td&gt;
&lt;td&gt;Discards the extra defined data so that the array length matches the input array&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Null&lt;/td&gt;
&lt;td&gt;Fills the missing elements with &lt;code&gt;null&lt;/code&gt; (for non-optional fields, &lt;code&gt;Null&lt;/code&gt; behaves the same as &lt;code&gt;Fill&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skip&lt;/td&gt;
&lt;td&gt;Leaves the extra defined data unchanged&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Typically, when receiving an array from the backend, you would instantiate a new object. In such cases, the array’s initial length is 0 (i.e., the input array length is greater than the defined array), so the behavior is governed by the MoreIndex enumeration. The default setting for &lt;code&gt;MoreIndex&lt;/code&gt; is &lt;code&gt;MoreIndex.Fill&lt;/code&gt;, meaning the input data is filled into the defined array element by element, which is the expected behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;That’s all the content. Thank you for reading. This project has evolved through years of practical use, iterative improvement, and refinement. I sincerely hope you find it useful in your projects. &lt;br&gt;
If you encounter any issues or have suggestions for improvements, &lt;br&gt;
please feel free to provide feedback through the following channels:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Submit issues or suggestions via GitHub Issues&lt;/li&gt;
&lt;li&gt;Email Yang Fan&amp;lt;&lt;a href="//mailto:yangfanzn@gmail.com"&gt;yangfanzn@gmail.com&lt;/a&gt;&amp;gt;&lt;/li&gt;
&lt;li&gt;Leave a comment in the discussion section&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>npm</category>
      <category>cmd</category>
    </item>
  </channel>
</rss>
