├── .gitignore ├── LICENSE ├── README.md ├── example_image ├── file.jpg ├── install.jpg ├── jar.jpg ├── jsonformat.gif └── plugin.jpg ├── flutter_json_format.iml ├── flutter_json_format.jar ├── remove_cache.sh ├── resources └── META-INF │ └── plugin.xml ├── src └── com │ └── zll │ └── format │ ├── Clazz.kt │ ├── ClazzGenerator.kt │ ├── DartJsonFormatAction.kt │ ├── Settings.kt │ ├── UiBuilder.kt │ └── Util.java └── test ├── Test.kt ├── temp.dart ├── test.dart ├── test.json ├── test2.json └── test3.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.war 15 | *.nar 16 | *.ear 17 | *.zip 18 | *.tar.gz 19 | *.rar 20 | 21 | /.idea/ 22 | /out/ 23 | 24 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 25 | hs_err_pid* 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 neverwoods 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Update 2 | #### ver 2.1 3 | 4 | generate 『toJson』 function to support converting object to map 5 | 6 | ```json 7 | { 8 | "name": "zll", 9 | "age": 29, 10 | "star": 4.5, 11 | "married": true 12 | } 13 | ``` 14 | 15 | ```dart 16 | class Test { 17 | String name; 18 | int age; 19 | double star; 20 | bool married; 21 | 22 | static Test fromMap(Map map) { 23 | if (map == null) return null; 24 | Test testBean = Test(); 25 | testBean.name = map['name']; 26 | testBean.age = map['age']; 27 | testBean.star = map['star']; 28 | testBean.married = map['married']; 29 | return testBean; 30 | } 31 | 32 | Map toJson() => { 33 | "name": name, 34 | "age": age, 35 | "star": star, 36 | "married": married, 37 | }; 38 | } 39 | ``` 40 | 41 | ```dart 42 | import 'dart:convert' 43 | 44 | var json = JsonEncoder().convert(obj); 45 | ``` 46 | 47 | ### Install 48 | #### 1. Download jar 49 | https://plugins.jetbrains.com/plugin/11551-dart-json-format 50 | 51 | #### 2. Search in IDE 52 | 53 | Plugins -> Browse repositories -> input "dart_json_format" 54 | 55 | ### Generate 56 | 57 | ![gif](example_image/jsonformat.gif) 58 | 59 | ### Examples 60 | 61 | #### 1. Simple data 62 | 63 | ```json 64 | { 65 | "name": "zll", 66 | "age": 29, 67 | "star": 4.5, 68 | "married": true 69 | } 70 | ``` 71 | 72 | ```dart 73 | class Test { 74 | String name; 75 | int age; 76 | double star; 77 | bool married; 78 | 79 | static Test fromMap(Map map) { 80 | if (map == null) return null; 81 | Test testBean = Test(); 82 | testBean.name = map['name']; 83 | testBean.age = map['age']; 84 | testBean.star = map['star']; 85 | testBean.married = map['married']; 86 | return testBean; 87 | } 88 | } 89 | ``` 90 | 91 | #### 2. Ojbect 92 | 93 | ```json 94 | { 95 | "programmer": { 96 | "name": "zll", 97 | "age": 29, 98 | "star": 4.5, 99 | "married": true 100 | } 101 | } 102 | ``` 103 | 104 | ```dart 105 | class Test { 106 | ProgrammerBean programmer; 107 | 108 | static Test fromMap(Map map) { 109 | if (map == null) return null; 110 | Test testBean = Test(); 111 | testBean.programmer = ProgrammerBean.fromMap(map['programmer']); 112 | return testBean; 113 | } 114 | } 115 | 116 | class ProgrammerBean { 117 | String name; 118 | int age; 119 | double star; 120 | bool married; 121 | 122 | static ProgrammerBean fromMap(Map map) { 123 | if (map == null) return null; 124 | ProgrammerBean programmerBean = ProgrammerBean(); 125 | programmerBean.name = map['name']; 126 | programmerBean.age = map['age']; 127 | programmerBean.star = map['star']; 128 | programmerBean.married = map['married']; 129 | return programmerBean; 130 | } 131 | } 132 | ``` 133 | 134 | #### 3. Array 135 | 136 | ```json 137 | { 138 | "names": ["zll", "kfc"], 139 | "ages": [29, 25], 140 | "stars": [4.5, 4.4], 141 | "marrieds": [true, false] 142 | } 143 | ``` 144 | 145 | ```dart 146 | class Test { 147 | List names; 148 | List ages; 149 | List stars; 150 | List marrieds; 151 | 152 | static Test fromMap(Map map) { 153 | if (map == null) return null; 154 | Test testBean = Test(); 155 | testBean.names = List()..addAll( 156 | (map['names'] as List ?? []).map((o) => o.toString()) 157 | ); 158 | testBean.ages = List()..addAll( 159 | (map['ages'] as List ?? []).map((o) => int.tryParse(o.toString())) 160 | ); 161 | testBean.stars = List()..addAll( 162 | (map['stars'] as List ?? []).map((o) => double.tryParse(o.toString())) 163 | ); 164 | testBean.marrieds = List()..addAll( 165 | (map['marrieds'] as List ?? []).map((o) => o.toString() == 'true') 166 | ); 167 | return testBean; 168 | } 169 | } 170 | ``` 171 | 172 | #### 4. Array of Object 173 | ```json 174 | { 175 | "programmers": [ 176 | { 177 | "name": "zll", 178 | "age": 29, 179 | "star": 4.5, 180 | "married": true 181 | },{ 182 | "name": "kfc", 183 | "age": 25, 184 | "star": 4.1, 185 | "married": false 186 | } 187 | ] 188 | } 189 | ``` 190 | 191 | ```dart 192 | class Test { 193 | List programmers; 194 | 195 | static Test fromMap(Map map) { 196 | if (map == null) return null; 197 | Test testBean = Test(); 198 | testBean.programmers = List()..addAll( 199 | (map['programmers'] as List ?? []).map((o) => ProgrammersBean.fromMap(o)) 200 | ); 201 | return testBean; 202 | } 203 | } 204 | 205 | class ProgrammersBean { 206 | String name; 207 | int age; 208 | double star; 209 | bool married; 210 | 211 | static ProgrammersBean fromMap(Map map) { 212 | if (map == null) return null; 213 | ProgrammersBean programmersBean = ProgrammersBean(); 214 | programmersBean.name = map['name']; 215 | programmersBean.age = map['age']; 216 | programmersBean.star = map['star']; 217 | programmersBean.married = map['married']; 218 | return programmersBean; 219 | } 220 | } 221 | ``` 222 | 223 | #### 5. Nested Array 224 | ```json 225 | { 226 | "something": [[[[[1]]]]] 227 | } 228 | ``` 229 | 230 | ```dart 231 | class Test { 232 | List>>>> something; 233 | 234 | static Test fromMap(Map map) { 235 | if (map == null) return null; 236 | Test testBean = Test(); 237 | testBean.something = List()..addAll( 238 | (map['something'] as List ?? []).map((o) => List()..addAll((o as List ?? []).map((oo) => List()..addAll((oo as List ?? []).map((ooo) => List()..addAll((ooo as List ?? []).map((oooo) => List()..addAll((oooo as List ?? []).map((ooooo) => int.tryParse(ooooo.toString())))))))))) 239 | ); 240 | return testBean; 241 | } 242 | } 243 | ``` 244 | 245 | #### 5. Nested Array of Object 246 | ```json 247 | { 248 | "something": [[[[[{ 249 | "name": "zll", 250 | "age": 29, 251 | "star": 4.5, 252 | "married": true 253 | }]]]]] 254 | } 255 | ``` 256 | 257 | ```dart 258 | class Test { 259 | List>>>> something; 260 | 261 | static Test fromMap(Map map) { 262 | if (map == null) return null; 263 | Test testBean = Test(); 264 | testBean.something = List()..addAll( 265 | (map['something'] as List ?? []).map((o) => List()..addAll((o as List ?? []).map((oo) => List()..addAll((oo as List ?? []).map((ooo) => List()..addAll((ooo as List ?? []).map((oooo) => List()..addAll((oooo as List ?? []).map((ooooo) => SomethingBean.fromMap(ooooo)))))))))) 266 | ); 267 | return testBean; 268 | } 269 | } 270 | 271 | class SomethingBean { 272 | String name; 273 | int age; 274 | double star; 275 | bool married; 276 | 277 | static SomethingBean fromMap(Map map) { 278 | if (map == null) return null; 279 | SomethingBean somethingBean = SomethingBean(); 280 | somethingBean.name = map['name']; 281 | somethingBean.age = map['age']; 282 | somethingBean.star = map['star']; 283 | somethingBean.married = map['married']; 284 | return somethingBean; 285 | } 286 | } 287 | ``` 288 | 289 | #### 6. Empty or Null 290 | ```json 291 | { 292 | "obj": null, 293 | "emptyList": [], 294 | "nullList": [null] 295 | } 296 | ``` 297 | 298 | ```dart 299 | class Test { 300 | dynamic obj; 301 | List emptyList; 302 | List nullList; 303 | 304 | static Test fromMap(Map map) { 305 | if (map == null) return null; 306 | Test testBean = Test(); 307 | testBean.obj = map['obj']; 308 | testBean.emptyList = map['emptyList']; 309 | testBean.nullList = map['nullList']; 310 | return testBean; 311 | } 312 | } 313 | ``` 314 | 315 | #### 7. Root Array 316 | ```json 317 | [ 318 | { 319 | "name": "zll", 320 | "age": 29, 321 | "star": 4.5, 322 | "married": true 323 | }, 324 | { 325 | "name": "kfc", 326 | "age": 25, 327 | "star": 4.1, 328 | "married": false 329 | } 330 | ] 331 | ``` 332 | 333 | ##### Take only array[0] to use 334 | 335 | ```dart 336 | class Test { 337 | String name; 338 | int age; 339 | double star; 340 | bool married; 341 | 342 | static Test fromMap(Map map) { 343 | if (map == null) return null; 344 | Test testBean = Test(); 345 | testBean.name = map['name']; 346 | testBean.age = map['age']; 347 | testBean.star = map['star']; 348 | testBean.married = map['married']; 349 | return testBean; 350 | } 351 | } 352 | ``` 353 | 354 | -------------------------------------------------------------------------------- /example_image/file.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neverwoodsS/idea_flutter_json_format/668a12cc1f1b0ee46dd36f46f33c1da7d5f9ce15/example_image/file.jpg -------------------------------------------------------------------------------- /example_image/install.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neverwoodsS/idea_flutter_json_format/668a12cc1f1b0ee46dd36f46f33c1da7d5f9ce15/example_image/install.jpg -------------------------------------------------------------------------------- /example_image/jar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neverwoodsS/idea_flutter_json_format/668a12cc1f1b0ee46dd36f46f33c1da7d5f9ce15/example_image/jar.jpg -------------------------------------------------------------------------------- /example_image/jsonformat.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neverwoodsS/idea_flutter_json_format/668a12cc1f1b0ee46dd36f46f33c1da7d5f9ce15/example_image/jsonformat.gif -------------------------------------------------------------------------------- /example_image/plugin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neverwoodsS/idea_flutter_json_format/668a12cc1f1b0ee46dd36f46f33c1da7d5f9ce15/example_image/plugin.jpg -------------------------------------------------------------------------------- /flutter_json_format.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /flutter_json_format.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neverwoodsS/idea_flutter_json_format/668a12cc1f1b0ee46dd36f46f33c1da7d5f9ce15/flutter_json_format.jar -------------------------------------------------------------------------------- /remove_cache.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | git rm -r --cached . 3 | git add . 4 | git commit -am 'git cache cleared' 5 | git push -------------------------------------------------------------------------------- /resources/META-INF/plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | com.zll.format 3 | flutter_json_format 4 | 2.1 5 | neverwoods 6 | 7 | 8 | Help to generate Dart data class from JSON string. 9 | 10 | 11 | 12 | fix issue#6; 13 | generate toJson function code; 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 | com.intellij.modules.lang 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/com/zll/format/Clazz.kt: -------------------------------------------------------------------------------- 1 | package com.zll.format 2 | 3 | import com.google.gson.JsonArray 4 | import com.google.gson.JsonObject 5 | 6 | abstract class Clazz( 7 | open val root: MutableList, 8 | open val name: String, 9 | open val content: Any?, 10 | open val children: List? 11 | ) { 12 | companion object { 13 | operator fun invoke(root: MutableList, name: String, any: Any?): Clazz { 14 | // 处理空值 15 | if (any == null || "null" == any.toString()) 16 | return EmptyClazz(root, name, any, null) 17 | 18 | // 处理对象 19 | if (any is JsonObject) 20 | return ObjectClazz(root, name, any, json2Clazz(root, any)) 21 | 22 | // 处理数组 23 | if (any is JsonArray) { 24 | return if (any.size() == 0) { 25 | ListClazz(root, name, any, null, null) 26 | } else { 27 | val temp = Clazz(root, name, any[0]) 28 | ListClazz(root, name, any, null, temp) 29 | } 30 | } 31 | 32 | // 处理基本类型 33 | if (any.isBoolean()) 34 | return BaseClazz(root, "bool", name, any, null) 35 | 36 | if (any.isInt() || any.isLong()) 37 | return BaseClazz(root, "int", name, any, null) 38 | 39 | if (any.isDouble() || any.isFloat()) 40 | return BaseClazz(root, "double", name, any, null) 41 | 42 | // 都不匹配的情况,默认为 String 类型 43 | return BaseClazz(root, "String", name, any, null) 44 | } 45 | 46 | fun json2Clazz(root: MutableList, jsonObject: JsonObject): List { 47 | val list = mutableListOf() 48 | for (o in jsonObject.entrySet()) { 49 | val entry = o as Map.Entry<*, *> 50 | list.add(Clazz(root, entry.key.toString(), entry.value)) 51 | } 52 | return list 53 | } 54 | 55 | private fun Any.isInt() = toString().toIntOrNull() != null 56 | private fun Any.isLong() = toString().toLongOrNull() != null 57 | private fun Any.isDouble() = toString().toDoubleOrNull() != null 58 | private fun Any.isFloat() = toString().toFloatOrNull() != null 59 | private fun Any.isBoolean() = toString().let { it == "true" || it == "false" } 60 | } 61 | 62 | fun getStatement() = "${getClassName()} ${getCamelName()};" 63 | fun getFieldName() = Util.toLowerCaseFirstOne(getClassName()) 64 | fun getCamelName() = name.split("_").reduce { acc, s -> "$acc${Util.toUpperCaseFirstOne(s)}" } 65 | fun getComment() = "$name : ${content.toString().replace("\n", "")}" 66 | fun getJsonAssignment() = "\"$name\": ${getCamelName()}" 67 | 68 | abstract fun getAssignments(parent: String): List 69 | abstract fun getClassName(): String 70 | abstract fun map(obj: String): String 71 | } 72 | 73 | data class EmptyClazz( 74 | override val root: MutableList, 75 | override val name: String, 76 | override val content: Any?, 77 | override val children: List? 78 | ) : Clazz(root, name, content, children) { 79 | 80 | override fun getClassName() = "dynamic" 81 | override fun getAssignments(parent: String) = listOf("$parent.${getCamelName()} = map['$name'];") 82 | override fun map(obj: String) = "" 83 | } 84 | 85 | data class BaseClazz( 86 | override val root: MutableList, 87 | val type: String, 88 | override val name: String, 89 | override val content: Any?, 90 | override val children: List? 91 | ) : Clazz(root, name, content, children) { 92 | 93 | override fun getClassName() = type 94 | override fun getAssignments(parent: String) = listOf("$parent.${getCamelName()} = map['$name'];") 95 | override fun map(obj: String): String { 96 | return when (type) { 97 | "bool" -> "$obj.toString() == 'true'" 98 | "int" -> "int.tryParse($obj.toString())" 99 | "double" -> "double.tryParse($obj.toString())" 100 | else -> "$obj.toString()" 101 | } 102 | } 103 | } 104 | 105 | data class ObjectClazz( 106 | override val root: MutableList, 107 | override val name: String, 108 | override val content: Any?, 109 | override val children: List? 110 | ) : Clazz(root, name, content, children) { 111 | init { 112 | root.add(this) 113 | } 114 | 115 | override fun getClassName() = "${Util.toUpperCaseFirstOne(name)}Bean" 116 | override fun getAssignments(parent: String) = listOf("$parent.${getCamelName()} = ${getClassName()}.fromMap(map['$name']);") 117 | override fun map(obj: String): String { 118 | return "${getClassName()}.fromMap($obj)" 119 | } 120 | } 121 | 122 | data class ListClazz( 123 | override val root: MutableList, 124 | override val name: String, 125 | override val content: Any?, 126 | override val children: List?, 127 | val child: Clazz? 128 | ) : Clazz(root, name, content, children) { 129 | 130 | override fun getClassName() = "List<${child?.getClassName() ?: "dynamic"}>" 131 | 132 | override fun map(obj: String): String { 133 | return if (child == null || child is EmptyClazz) "List()..addAll($obj as List)" 134 | else "List()..addAll(($obj as List ?? []).map((${obj}o) => ${child.map("${obj}o")}))" 135 | } 136 | 137 | override fun getAssignments(parent: String): List { 138 | return if (child == null || child is EmptyClazz) listOf("$parent.${getCamelName()} = map['$name'];") 139 | else listOf( 140 | "$parent.$name = List()..addAll(", 141 | " (map['$name'] as List ?? []).map((o) => ${child.map("o")})", 142 | ");" 143 | ) 144 | } 145 | } -------------------------------------------------------------------------------- /src/com/zll/format/ClazzGenerator.kt: -------------------------------------------------------------------------------- 1 | package com.zll.format 2 | 3 | import com.google.gson.JsonArray 4 | import com.google.gson.JsonObject 5 | import com.google.gson.JsonParseException 6 | import com.google.gson.JsonParser 7 | import java.lang.IllegalStateException 8 | 9 | class ClazzGenerator(val settings: Settings?) { 10 | 11 | fun generate(name: String, string: String) = try { 12 | JsonParser().parse(string).let { 13 | when (it) { 14 | is JsonObject -> it.asJsonObject 15 | is JsonArray -> it.asJsonArray[0].asJsonObject 16 | else -> null 17 | } 18 | }.let { obj -> 19 | mutableListOf().let { 20 | Clazz(it, name, obj) to it 21 | } 22 | }.let { (clazz, clazzes) -> 23 | clazzes.reversed() 24 | .map { printClazz(it == clazz, it, 0) } 25 | .reduce { acc, s -> "$acc\n\n$s" } 26 | } 27 | } catch (jsonParseException: JsonParseException) { 28 | jsonParseException.printStackTrace() 29 | "error: not supported json" 30 | } catch (illegalStateException: IllegalStateException) { 31 | illegalStateException.printStackTrace() 32 | 33 | if (illegalStateException.message?.startsWith("Not a JSON Object") == true) { 34 | "error: not supported json" 35 | } else { 36 | "error: unknown" 37 | } 38 | } 39 | 40 | private fun printClazz(keepName: Boolean, clazz: Clazz, space: Int): String { 41 | val sb = StringBuilder() 42 | 43 | var spaceStr = "" 44 | repeat(space) { spaceStr += " " } 45 | 46 | val className = Util.toUpperCaseFirstOne((if (keepName) clazz.name else clazz.getClassName())) 47 | 48 | if (settings?.generateComments == true) { 49 | clazz.children?.map { 50 | "/// ${it.getComment()}\n" 51 | }?.forEach { 52 | sb.append(it) 53 | } 54 | sb.append("\n") 55 | } 56 | 57 | // 输出 class 头 58 | sb.append(spaceStr).append("class ").append(className).append(" {") 59 | sb.append("\n") 60 | 61 | // 输出属性声明 62 | clazz.children?.map { 63 | "$spaceStr ${it.getStatement()}\n" 64 | }?.forEach { 65 | sb.append(it) 66 | } 67 | 68 | // 输出 fromMap 头 69 | sb.append("\n") 70 | sb.append("$spaceStr static ").append(className).append(" fromMap(Map map) {") 71 | sb.append("\n") 72 | sb.append("$spaceStr ").append("if (map == null) return null;") 73 | sb.append("\n") 74 | sb.append("$spaceStr ").append(className).append(" ").append(clazz.getFieldName()).append(" = ").append(className).append("();") 75 | sb.append("\n") 76 | 77 | // 输出数据提取及转换 78 | clazz.children?.flatMap { it.getAssignments(clazz.getFieldName()) }?.filterNot { it.isEmpty() }?.map { 79 | "$spaceStr $it\n" 80 | }?.forEach { 81 | sb.append(it) 82 | } 83 | 84 | // 输出 fromMap 尾 85 | sb.append("$spaceStr return ${clazz.getFieldName()};") 86 | sb.append("\n") 87 | sb.append("$spaceStr }") 88 | 89 | // 输出 toJson 头 90 | sb.append("\n") 91 | sb.append("\n") 92 | sb.append("$spaceStr Map toJson() => {") 93 | sb.append("\n") 94 | 95 | // 输出数据提取及转换 96 | clazz.children?.map { "${it.getJsonAssignment()}," }?.map { 97 | "$spaceStr $it\n" 98 | }?.forEach { 99 | sb.append(it) 100 | } 101 | 102 | // 输入 toJson 尾 103 | sb.append("$spaceStr };") 104 | 105 | // 输出 class 尾 106 | sb.append("\n") 107 | sb.append(spaceStr).append("}") 108 | 109 | return sb.toString() 110 | } 111 | } -------------------------------------------------------------------------------- /src/com/zll/format/DartJsonFormatAction.kt: -------------------------------------------------------------------------------- 1 | package com.zll.format 2 | 3 | import com.intellij.openapi.actionSystem.AnAction 4 | import com.intellij.openapi.actionSystem.AnActionEvent 5 | import com.intellij.openapi.actionSystem.PlatformDataKeys 6 | import com.intellij.openapi.editor.Editor 7 | import com.intellij.openapi.project.Project 8 | import com.intellij.psi.util.PsiUtilBase 9 | import javax.swing.JFrame 10 | 11 | class DartJsonFormatAction : AnAction() { 12 | override fun actionPerformed(event: AnActionEvent) { 13 | PsiUtilBase.getPsiFileInEditor(event.getData(PlatformDataKeys.EDITOR) as Editor, 14 | event.getData(PlatformDataKeys.PROJECT) as Project) 15 | ?.let { UiBuilder(it.project, it.virtualFile) } 16 | ?.let { 17 | JFrame("dart json format").apply { 18 | setSize(700, 520) 19 | defaultCloseOperation = JFrame.DISPOSE_ON_CLOSE 20 | add(it.build()) 21 | isVisible = true 22 | }.apply { it.frame = this } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/com/zll/format/Settings.kt: -------------------------------------------------------------------------------- 1 | package com.zll.format 2 | 3 | import com.intellij.ide.util.PropertiesComponent 4 | 5 | class Settings { 6 | 7 | companion object { 8 | private const val KEY_COMMENT = "dart_json_format_comment" 9 | } 10 | 11 | var generateComments: Boolean 12 | 13 | init { 14 | val propertiesComponent = PropertiesComponent.getInstance() 15 | generateComments = propertiesComponent.getBoolean(KEY_COMMENT, true) 16 | } 17 | 18 | fun save() = PropertiesComponent.getInstance().apply { 19 | setValue(KEY_COMMENT, generateComments.toString()) 20 | } 21 | } -------------------------------------------------------------------------------- /src/com/zll/format/UiBuilder.kt: -------------------------------------------------------------------------------- 1 | package com.zll.format 2 | 3 | import com.intellij.openapi.project.Project 4 | import com.intellij.openapi.vfs.VirtualFile 5 | import com.intellij.ui.components.JBScrollPane 6 | import com.zll.format.ClazzGenerator 7 | import com.zll.format.Settings 8 | import com.zll.format.Util 9 | import javax.swing.* 10 | 11 | class UiBuilder(private val project: Project, private val virtualFile: VirtualFile) { 12 | 13 | var frame: JFrame? = null 14 | 15 | fun build(): JComponent { 16 | return JPanel().apply { 17 | placeComponents(this) 18 | } 19 | } 20 | 21 | private fun placeComponents(panel: JPanel) = panel.apply { 22 | val className = Util.toUpperCaseFirstOne(virtualFile.nameWithoutExtension).split("_").reduce { acc, s -> "$acc${Util.toUpperCaseFirstOne(s)}" } 23 | val settings = Settings() 24 | 25 | layout = null 26 | 27 | val tipLabel = JLabel("class name: $className").apply { 28 | setBounds(10, 0, 500, 40) 29 | } 30 | 31 | val jsonText = JTextArea().apply { 32 | setBounds(10,50,680,400) 33 | } 34 | 35 | val commentCb = JCheckBox("generate comments", settings.generateComments).apply { 36 | setBounds(10, 460, 200, 30) 37 | } 38 | 39 | add(JButton("ok").apply { 40 | setBounds(600, 460, 80, 30) 41 | isVisible = true 42 | addActionListener { 43 | // 保存配置 44 | settings.generateComments = commentCb.isSelected 45 | settings.save() 46 | 47 | // 开始生成代码 48 | val classesString = ClazzGenerator(settings).generate(className, jsonText.text) 49 | if (classesString.startsWith("error:")) { 50 | tipLabel.text = classesString 51 | } else { 52 | Util.writeToFile(project, virtualFile, classesString) 53 | frame?.dispose() 54 | } 55 | } 56 | }) 57 | 58 | add(JBScrollPane(jsonText).apply { 59 | verticalScrollBarPolicy = JBScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED 60 | horizontalScrollBarPolicy = JBScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED 61 | setBounds(10, 50, 680, 400) 62 | }) 63 | 64 | add(commentCb) 65 | add(tipLabel) 66 | } 67 | } -------------------------------------------------------------------------------- /src/com/zll/format/Util.java: -------------------------------------------------------------------------------- 1 | package com.zll.format; 2 | 3 | import com.intellij.openapi.command.WriteCommandAction; 4 | import com.intellij.openapi.project.Project; 5 | import com.intellij.openapi.vfs.VirtualFile; 6 | import java.awt.*; 7 | import java.awt.datatransfer.Clipboard; 8 | import java.awt.datatransfer.StringSelection; 9 | import java.awt.datatransfer.Transferable; 10 | import java.io.IOException; 11 | 12 | /** 13 | * Created by zhangll on 2018/8/3. 14 | */ 15 | public class Util { 16 | /** 17 | * 将字符串复制到剪切板。 18 | */ 19 | public static void setSysClipboardText(String writeMe) { 20 | Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard(); 21 | Transferable tText = new StringSelection(writeMe); 22 | clip.setContents(tText, null); 23 | } 24 | 25 | // 首字母转大写 26 | public static String toUpperCaseFirstOne(String s) { 27 | if (s.isEmpty()) return s; 28 | if(Character.isUpperCase(s.charAt(0))) 29 | return s; 30 | else 31 | return Character.toUpperCase(s.charAt(0)) + s.substring(1); 32 | } 33 | 34 | // 首字母转小写 35 | public static String toLowerCaseFirstOne(String s) { 36 | if (s.isEmpty()) return s; 37 | if(Character.isLowerCase(s.charAt(0))) 38 | return s; 39 | else 40 | return Character.toLowerCase(s.charAt(0)) + s.substring(1); 41 | } 42 | 43 | // 将 string 写入文件 44 | public static void writeToFile(Project project, VirtualFile file, String content) { 45 | Runnable runnable = () -> { 46 | try { 47 | file.setBinaryContent(content.getBytes()); 48 | } catch (IOException e) { 49 | e.printStackTrace(); 50 | } 51 | }; 52 | 53 | WriteCommandAction.runWriteCommandAction(project, runnable); 54 | } 55 | } -------------------------------------------------------------------------------- /test/Test.kt: -------------------------------------------------------------------------------- 1 | import com.zll.format.ClazzGenerator 2 | import java.io.File 3 | 4 | fun main(args: Array) { 5 | val json = File("test/test.json").readText() 6 | // val obj = JsonObject().apply { 7 | //// addProperty("test0", "3") 8 | //// addProperty("test1", false) 9 | //// addProperty("test2", 2) 10 | // 11 | // val array1 = JsonArray() 12 | // val array2 = JsonArray() 13 | // val array3 = JsonArray() 14 | // val array4 = JsonArray() 15 | // array1.add(array2) 16 | // array2.add(array3) 17 | // array2.add(array4) 18 | // array3.add(1) 19 | // array3.add(2) 20 | // array4.add(3) 21 | // array4.add(4) 22 | // add("array", array1) 23 | // } 24 | 25 | println(ClazzGenerator(null).generate("Test", json)) 26 | } -------------------------------------------------------------------------------- /test/temp.dart: -------------------------------------------------------------------------------- 1 | class Temp { 2 | String code; 3 | String message; 4 | bool success; 5 | dynamic emptyList; 6 | dynamic nullObj; 7 | DataBean data; 8 | ExtraDataBean extraData; 9 | List boolList; 10 | List doubleList; 11 | List intList; 12 | List testFromList; 13 | List nullList; 14 | 15 | static Temp fromMap(Map map) { 16 | Temp test = new Temp(); 17 | test.code = map['code']; 18 | test.message = map['message']; 19 | test.success = map['success']; 20 | test.emptyList = map['emptyList']; 21 | test.nullObj = map['nullObj']; 22 | test.nullList = map['nullList']; 23 | test.data = DataBean.fromMap(map['data']); 24 | test.extraData = ExtraDataBean.fromMap(map['extraData']); 25 | test.testFromList = TestFromListListBean.fromMapList(map['testFromList']); 26 | 27 | List dynamicList0 = map['boolList'] ?? []; 28 | test.boolList = new List(); 29 | test.boolList.addAll(dynamicList0.map((o) => o.toString() == 'true')); 30 | 31 | List dynamicList1 = map['doubleList'] ?? []; 32 | test.doubleList = new List(); 33 | test.doubleList.addAll(dynamicList1.map((o) => double.parse(o.toString()))); 34 | 35 | List dynamicList2 = map['intList'] ?? []; 36 | test.intList = new List(); 37 | test.intList.addAll(dynamicList2.map((o) => int.parse(o.toString()))); 38 | 39 | return test; 40 | } 41 | 42 | static List fromMapList(dynamic mapList) { 43 | if (mapList == null) return []; 44 | List list = new List(mapList.length); 45 | for (int i = 0; i < mapList.length; i++) { 46 | list[i] = fromMap(mapList[i]); 47 | } 48 | return list; 49 | } 50 | 51 | } 52 | 53 | class DataBean { 54 | ExpressAddressBean expressAddress; 55 | FacetofaceAddressBean facetofaceAddress; 56 | OrderBean order; 57 | 58 | static DataBean fromMap(Map map) { 59 | DataBean dataBean = new DataBean(); 60 | dataBean.expressAddress = ExpressAddressBean.fromMap(map['expressAddress']); 61 | dataBean.facetofaceAddress = FacetofaceAddressBean.fromMap(map['facetofaceAddress']); 62 | dataBean.order = OrderBean.fromMap(map['order']); 63 | return dataBean; 64 | } 65 | 66 | static List fromMapList(dynamic mapList) { 67 | if (mapList == null) return []; 68 | List list = new List(mapList.length); 69 | for (int i = 0; i < mapList.length; i++) { 70 | list[i] = fromMap(mapList[i]); 71 | } 72 | return list; 73 | } 74 | } 75 | 76 | class ExtraDataBean { 77 | 78 | static ExtraDataBean fromMap(Map map) { 79 | ExtraDataBean extraDataBean = new ExtraDataBean(); 80 | return extraDataBean; 81 | } 82 | 83 | static List fromMapList(dynamic mapList) { 84 | if (mapList == null) return []; 85 | List list = new List(mapList.length); 86 | for (int i = 0; i < mapList.length; i++) { 87 | list[i] = fromMap(mapList[i]); 88 | } 89 | return list; 90 | } 91 | } 92 | 93 | class TestFromListListBean { 94 | String testKey; 95 | 96 | static TestFromListListBean fromMap(Map map) { 97 | TestFromListListBean testFromListListBean = new TestFromListListBean(); 98 | testFromListListBean.testKey = map['testKey']; 99 | return testFromListListBean; 100 | } 101 | 102 | static List fromMapList(dynamic mapList) { 103 | if (mapList == null) return []; 104 | List list = new List(mapList.length); 105 | for (int i = 0; i < mapList.length; i++) { 106 | list[i] = fromMap(mapList[i]); 107 | } 108 | return list; 109 | } 110 | } 111 | 112 | class ExpressAddressBean { 113 | String address; 114 | String createdDatetime; 115 | String receiver; 116 | String receiverCellphone; 117 | String sid; 118 | String title; 119 | String type; 120 | String userSid; 121 | int sortNumber; 122 | 123 | static ExpressAddressBean fromMap(Map map) { 124 | ExpressAddressBean expressAddressBean = new ExpressAddressBean(); 125 | expressAddressBean.address = map['address']; 126 | expressAddressBean.createdDatetime = map['createdDatetime']; 127 | expressAddressBean.receiver = map['receiver']; 128 | expressAddressBean.receiverCellphone = map['receiverCellphone']; 129 | expressAddressBean.sid = map['sid']; 130 | expressAddressBean.title = map['title']; 131 | expressAddressBean.type = map['type']; 132 | expressAddressBean.userSid = map['userSid']; 133 | expressAddressBean.sortNumber = map['sortNumber']; 134 | return expressAddressBean; 135 | } 136 | 137 | static List fromMapList(dynamic mapList) { 138 | if (mapList == null) return []; 139 | List list = new List(mapList.length); 140 | for (int i = 0; i < mapList.length; i++) { 141 | list[i] = fromMap(mapList[i]); 142 | } 143 | return list; 144 | } 145 | } 146 | 147 | class FacetofaceAddressBean { 148 | String address; 149 | String receiver; 150 | String receiverCellphone; 151 | String sid; 152 | String title; 153 | String type; 154 | String userSid; 155 | int sortNumber; 156 | 157 | static FacetofaceAddressBean fromMap(Map map) { 158 | FacetofaceAddressBean facetofaceAddressBean = new FacetofaceAddressBean(); 159 | facetofaceAddressBean.address = map['address']; 160 | facetofaceAddressBean.receiver = map['receiver']; 161 | facetofaceAddressBean.receiverCellphone = map['receiverCellphone']; 162 | facetofaceAddressBean.sid = map['sid']; 163 | facetofaceAddressBean.title = map['title']; 164 | facetofaceAddressBean.type = map['type']; 165 | facetofaceAddressBean.userSid = map['userSid']; 166 | facetofaceAddressBean.sortNumber = map['sortNumber']; 167 | return facetofaceAddressBean; 168 | } 169 | 170 | static List fromMapList(dynamic mapList) { 171 | if (mapList == null) return []; 172 | List list = new List(mapList.length); 173 | for (int i = 0; i < mapList.length; i++) { 174 | list[i] = fromMap(mapList[i]); 175 | } 176 | return list; 177 | } 178 | } 179 | 180 | class OrderBean { 181 | String brokerAvatar; 182 | String brokerCellphone; 183 | String brokerName; 184 | String brokerSid; 185 | String code; 186 | String cover; 187 | String createdDatetime; 188 | String deliveryAddressSid; 189 | String orderStatus; 190 | String orderStatusDesp; 191 | String orderType; 192 | String payType; 193 | String postTicketSid; 194 | String receiveDatetime; 195 | String receiver; 196 | String receiverAddress; 197 | String receiverCellphone; 198 | String receiverTitle; 199 | String remark; 200 | String requestDatetime; 201 | String showName; 202 | String showSchedule; 203 | String showScheduleSid; 204 | String showSid; 205 | String sid; 206 | String stateDesp; 207 | String ticketSid; 208 | String tradeType; 209 | String userCellphone; 210 | String userLeaveMessage; 211 | String userSid; 212 | String venueAddress; 213 | String venueName; 214 | bool isDelete; 215 | bool isSequential; 216 | double brokerStars; 217 | int bidding; 218 | int brokerDealNum; 219 | int deliveryFee; 220 | int evaluateStarts; 221 | int ticketPrice; 222 | int ticketQuantity; 223 | int totalPrice; 224 | List orderStatusArray; 225 | 226 | static OrderBean fromMap(Map map) { 227 | OrderBean orderBean = new OrderBean(); 228 | orderBean.brokerAvatar = map['brokerAvatar']; 229 | orderBean.brokerCellphone = map['brokerCellphone']; 230 | orderBean.brokerName = map['brokerName']; 231 | orderBean.brokerSid = map['brokerSid']; 232 | orderBean.code = map['code']; 233 | orderBean.cover = map['cover']; 234 | orderBean.createdDatetime = map['createdDatetime']; 235 | orderBean.deliveryAddressSid = map['deliveryAddressSid']; 236 | orderBean.orderStatus = map['orderStatus']; 237 | orderBean.orderStatusDesp = map['orderStatusDesp']; 238 | orderBean.orderType = map['orderType']; 239 | orderBean.payType = map['payType']; 240 | orderBean.postTicketSid = map['postTicketSid']; 241 | orderBean.receiveDatetime = map['receiveDatetime']; 242 | orderBean.receiver = map['receiver']; 243 | orderBean.receiverAddress = map['receiverAddress']; 244 | orderBean.receiverCellphone = map['receiverCellphone']; 245 | orderBean.receiverTitle = map['receiverTitle']; 246 | orderBean.remark = map['remark']; 247 | orderBean.requestDatetime = map['requestDatetime']; 248 | orderBean.showName = map['showName']; 249 | orderBean.showSchedule = map['showSchedule']; 250 | orderBean.showScheduleSid = map['showScheduleSid']; 251 | orderBean.showSid = map['showSid']; 252 | orderBean.sid = map['sid']; 253 | orderBean.stateDesp = map['stateDesp']; 254 | orderBean.ticketSid = map['ticketSid']; 255 | orderBean.tradeType = map['tradeType']; 256 | orderBean.userCellphone = map['userCellphone']; 257 | orderBean.userLeaveMessage = map['userLeaveMessage']; 258 | orderBean.userSid = map['userSid']; 259 | orderBean.venueAddress = map['venueAddress']; 260 | orderBean.venueName = map['venueName']; 261 | orderBean.isDelete = map['isDelete']; 262 | orderBean.isSequential = map['isSequential']; 263 | orderBean.brokerStars = map['brokerStars']; 264 | orderBean.bidding = map['bidding']; 265 | orderBean.brokerDealNum = map['brokerDealNum']; 266 | orderBean.deliveryFee = map['deliveryFee']; 267 | orderBean.evaluateStarts = map['evaluateStarts']; 268 | orderBean.ticketPrice = map['ticketPrice']; 269 | orderBean.ticketQuantity = map['ticketQuantity']; 270 | orderBean.totalPrice = map['totalPrice']; 271 | orderBean.orderStatusArray = OrderStatusArrayListBean.fromMapList(map['orderStatusArray']); 272 | return orderBean; 273 | } 274 | 275 | static List fromMapList(dynamic mapList) { 276 | if (mapList == null) return []; 277 | List list = new List(mapList.length); 278 | for (int i = 0; i < mapList.length; i++) { 279 | list[i] = fromMap(mapList[i]); 280 | } 281 | return list; 282 | } 283 | } 284 | 285 | class OrderStatusArrayListBean { 286 | String operateDatetime; 287 | String operateUserSid; 288 | String operateUsername; 289 | String orderSid; 290 | String orderType; 291 | String sid; 292 | String state; 293 | 294 | static OrderStatusArrayListBean fromMap(Map map) { 295 | OrderStatusArrayListBean orderStatusArrayListBean = new OrderStatusArrayListBean(); 296 | orderStatusArrayListBean.operateDatetime = map['operateDatetime']; 297 | orderStatusArrayListBean.operateUserSid = map['operateUserSid']; 298 | orderStatusArrayListBean.operateUsername = map['operateUsername']; 299 | orderStatusArrayListBean.orderSid = map['orderSid']; 300 | orderStatusArrayListBean.orderType = map['orderType']; 301 | orderStatusArrayListBean.sid = map['sid']; 302 | orderStatusArrayListBean.state = map['state']; 303 | return orderStatusArrayListBean; 304 | } 305 | 306 | static List fromMapList(dynamic mapList) { 307 | if (mapList == null) return []; 308 | List list = new List(mapList.length); 309 | for (int i = 0; i < mapList.length; i++) { 310 | list[i] = fromMap(mapList[i]); 311 | } 312 | return list; 313 | } 314 | } 315 | -------------------------------------------------------------------------------- /test/test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'temp.dart'; 3 | import 'dart:io'; 4 | 5 | main() async { 6 | var json = await File('test.json').readAsString(); 7 | var map = JsonDecoder().convert(json); 8 | 9 | Temp temp = Temp.fromMap(map); 10 | print(temp.data.expressAddress.receiverCellphone); 11 | print(temp.intList); 12 | print(temp.emptyList); 13 | print(temp.nullList); 14 | print(temp.nullObj); 15 | print(temp.testFromList); 16 | } -------------------------------------------------------------------------------- /test/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": "2000", 3 | "data": { 4 | "expressAddress": { 5 | "address": "控江路1209", 6 | "createdDatetime": "2015-12-09 19:36:38", 7 | "receiver": "张**", 8 | "receiverCellphone": "1502379****", 9 | "sid": "c25c1954ca204dee8fc18f51bcc71a3e", 10 | "sortNumber": 1, 11 | "title": "先生", 12 | "type": "EXPRESS", 13 | "userSid": "a19cf6e3586143d283dd4128c456bfaf" 14 | }, 15 | "facetofaceAddress": { 16 | "address": "", 17 | "receiver": "罗", 18 | "receiverCellphone": "1388345****", 19 | "sid": "001190e19e754001b53701d0aa81bfe0", 20 | "sortNumber": 1, 21 | "title": "女士", 22 | "type": "FACETOFACE", 23 | "userSid": "a19cf6e3586143d283dd4128c456bfaf" 24 | }, 25 | "order": { 26 | "bidding": 2300, 27 | "brokerAvatar": "broker/getAvatar?key=avatar/b82378ccaccb403c9d8420274372c904", 28 | "brokerCellphone": "1347282****", 29 | "brokerDealNum": 15, 30 | "brokerName": "王**", 31 | "brokerSid": "b82378ccaccb403c9d8420274372c904", 32 | "brokerStars": 4.5, 33 | "code": "1512151307270113", 34 | "cover": "show/getPoster?key=52f30bbce4ef4122919cbc95c2f01c36/52f30bbce4ef4122919cbc95c2f01c36", 35 | "createdDatetime": "2015-12-15 13:07:28", 36 | "deliveryAddressSid": "c25c1954ca204dee8fc18f51bcc71a3e", 37 | "deliveryFee": 0, 38 | "evaluateStarts": 0, 39 | "isDelete": false, 40 | "isSequential": false, 41 | "orderStatus": "CLOSED", 42 | "orderStatusArray": [{ 43 | "operateDatetime": "2015-12-15 13:07:28", 44 | "operateUserSid": "b82378ccaccb403c9d8420274372c904", 45 | "operateUsername": "王**", 46 | "orderSid": "21bc3cc65e9e47af952c1f4f1f0fd85a", 47 | "orderType": "1", 48 | "sid": "04940ed81540466ea4408f79989a5d54", 49 | "state": "TAKING" 50 | }], 51 | "orderStatusDesp": "", 52 | "orderType": "1", 53 | "payType": "", 54 | "postTicketSid": "65cc6d54300349e984134ecd0faf3ede", 55 | "receiveDatetime": "2015-12-15 13:07:28", 56 | "receiver": "张**", 57 | "receiverAddress": "控江路1209", 58 | "receiverCellphone": "1502379****", 59 | "receiverTitle": "先生", 60 | "remark": "", 61 | "requestDatetime": "2015-12-15 13:07:28", 62 | "showName": "Love Radio 品冠 现在你在哪里 巡回演唱会上海站", 63 | "showSchedule": "2016-01-09 19:30:00", 64 | "showScheduleSid": "eecfd0657fb445a7a36abedc9b621c89", 65 | "showSid": "52f30bbce4ef4122919cbc95c2f01c36", 66 | "sid": "21bc3cc65e9e47af952c1f4f1f0fd85a", 67 | "stateDesp": "已关闭", 68 | "ticketPrice": 88000, 69 | "ticketQuantity": 1, 70 | "ticketSid": "c4583aa8a79a478e8e5cd14691028430", 71 | "totalPrice": 2300, 72 | "tradeType": "EXPRESS", 73 | "userCellphone": "1502379****", 74 | "userLeaveMessage": "", 75 | "userSid": "a19cf6e3586143d283dd4128c456bfaf", 76 | "venueAddress": "上海市长宁区武夷路777号", 77 | "venueName": "上海国际体操中心" 78 | } 79 | }, 80 | "testFromList": [ 81 | { 82 | "testKey" : "testValue" 83 | } 84 | ], 85 | "extraData": {}, 86 | "message": "", 87 | "success": true, 88 | "intList": [1, 2, 3], 89 | "boolList": [true, false, true, true], 90 | "doubleList": [0.0, 1.1, 2.2, 3.3], 91 | "emptyList": [], 92 | "nullList": [null], 93 | "nullObj": null 94 | } -------------------------------------------------------------------------------- /test/test2.json: -------------------------------------------------------------------------------- 1 | { 2 | "params": [[ 3 | [ 4 | "completedLength", 5 | "connections", 6 | "dir", 7 | "downloadSpeed", 8 | "files", 9 | "gid", 10 | "infoHash", 11 | "numPieces", 12 | "numSeeders", 13 | "pieceLength", 14 | "seeder", 15 | "status", 16 | "totalLength", 17 | "uploadLength", 18 | "uploadSpeed" 19 | ] 20 | ]] 21 | } -------------------------------------------------------------------------------- /test/test3.json: -------------------------------------------------------------------------------- 1 | { 2 | "mobile" : "17689209851", 3 | "avatar" : "http:\/\/album.test.getqood.com\/images\/file\/D9360020804F73C96004009503B3F72387583552.PNG", 4 | "organization__id" : "1197146792697790465", 5 | "birthdate" : "2018-12-13T00:00:00.000+0800", 6 | "type" : "普通会员", 7 | "apply_time" : "2011-08-23T00:00:00.000+0800", 8 | "nick_name" : "学员测试", 9 | "id" : "1139173367484514632", 10 | "course_title" : "1", 11 | "created_at" : "2018-12-14T09:48:43.000+0800", 12 | "updated_at" : "2018-12-25T18:56:31.000+0800", 13 | "organization_name" : "罗", 14 | "gender" : "男" 15 | } --------------------------------------------------------------------------------