将 POJO 转换为 JSON 的简单插件
- 支持Java中您能想到的任何类型
- Support Java17 and last
- 支持 Java14 Records JEP-359
- 部分支持 Jackson 和 Fastjson 注解
- 支持转换
- Inner Class
- Global Variable
- Local Variable
- Constructor Parameter
- Method Parameter
- Java - 完全支持
- Kotlin - 完全支持
-
请注意,光标的位置会影响结果!
-
打开class文件 > 移动光标到 Class/Variable/Parameter > 右键单击 > Copy JSON > JSON 结果将复制到剪贴板
-
打开class文件 > 移动光标到 Class/Variable/Parameter > Alt + Insert > Copy JSON > JSON 结果将复制到剪贴板
-
项目视图选择多个class文件 > 右键单击 > Copy JSON > JSON 结果将生成到 Scratches 文件夹中
-
IDEA中安装:
- Preferences(Settings) > Plugins > Marketplace > 搜索"POJO to JSON" > Install
-
手动安装:
- plugin -> Preferences(Settings) > Plugins > ⚙️ > Install plugin from disk... -> Select the plug-in package and install(No need to unzip)
-
为什么使用的时候总是报错?
This class reference level exceeds maximum limit or has nested references!
当程序抛出此警告时,只有两种可能性。
-
这个 class 或父级 class 存在嵌套引用
eg:
public class A { private B b; public class B { private A a; } }
{ "b":{ "a":{ "b":{ "a":{ ...... } } } } }
or
public class A { private A a; }
{ "a":{ "a":{ "a":{ "a":{ ...... } } } } }
-
当前class的引用层级 > 200
eg:
public class A { private B _0; public class B { private C _1; public class C { private D _2; public class D { // _3 ..... _201.. } } } }
{ "_0": { "_1": { "_2": { "......_201":{} } } } }
也许这两种情况都会发生在实体上,但这个实体不适合JSON。
您可以尝试使用 Jackson 序列化您的 POJO 看看会发生什么。
如果没有任何异常, 可以将您的POJO作为例子向此repo的Issues提交BUG :)
-
-
但是如何解决这个问题呢?
您可以尝试以下方法。
-
@JsonProperty and @JSONField
import com.alibaba.fastjson.annotation.JSONField; import com.fasterxml.jackson.annotation.JsonProperty; public class User { @JsonProperty("name") private String username; @JSONField(name = "pass") private String password; }
paste result:
{ "name": "", "pass": "" }
-
@JsonIgnore or Javadoc tags JsonIgnore
import com.fasterxml.jackson.annotation.JsonIgnore; public class User { @JsonIgnore private String username; private String password; }
或者当您没有导入 jackson 库时
public class JsonIgnoreDocTestPOJO { /** * @JsonIgnore */ private String username; private String password; }
paste result:
{ "password": "" }
-
@JsonIgnoreProperties or Javadoc tags JsonIgnoreProperties
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import java.util.List; public class User { private String username; @JsonIgnoreProperties({"users", "aaa", "bbb"}) private List<Role> roles; public class Role { private String roleName; private List<User> users; } }
或者当您没有导入 jackson 库时
import java.util.List; public class User { private String username; /** * @JsonIgnoreProperties users, aaa, bbb */ private List<Role> roles; public class Role { private String roleName; private List<User> users; } }
paste result:
{ "username": "", "roles": [ { "roleName": "" } ] }
您在使用过程中可能会遇到此问题。
This class reference level exceeds maximum limit or has nested references!
上述方法可以很好地解决嵌套引用问题。
-
@JsonIgnoreType
import com.fasterxml.jackson.annotation.JsonIgnoreType; import java.util.List; public class User { private String username; private List<Role> roles; @JsonIgnoreType public class Role { private String roleName; private List<User> users; } }
paste result:
{ "username": "", "roles": [] }
SpEL expression 能做什么?
-
这是默认配置。一般情况下不需要修改。
com.fasterxml.jackson.databind.JsonNode=#{#object.getValue()} com.fasterxml.jackson.databind.node.ArrayNode=#{#array.getValue()} com.fasterxml.jackson.databind.node.ObjectNode=#{#object.getValue()} java.lang.Boolean=#{#boolean.getValue()} java.lang.CharSequence=#{#field.getName() + '_' + #shortuuid.getValue()} java.lang.Character=#{'c'} java.lang.Double=#{#decimal.getValue()} java.lang.Float=#{#decimal.getValue()} java.lang.Number=#{#integer.getValue()} java.math.BigDecimal=#{#decimal.getValue()} java.time.LocalDate=#{#datetime.getValue('yyyy-MM-dd')} java.time.LocalDateTime=#{#datetime.getValue('yyyy-MM-dd HH:mm:ss')} java.time.LocalTime=#{#datetime.getValue('HH:mm:ss')} java.time.YearMonth=#{#datetime.getValue('yyyy-MM')} java.time.ZonedDateTime=#{#datetime.getValue()} java.time.temporal.Temporal=#{#temporal.getValue()} java.util.AbstractMap=#{#object.getValue()} java.util.Date=#{#datetime.getValue('yyyy-MM-dd HH:mm:ss')} java.util.Map=#{#object.getValue()} java.util.UUID=#{#uuid.getValue()}
-
如果你想问之前的
Copy JSON and Random Values
选项去哪儿了?使用如下配置即可达到之前的效果。com.fasterxml.jackson.databind.JsonNode=#{#object.getValue()} com.fasterxml.jackson.databind.node.ArrayNode=#{#array.getValue()} com.fasterxml.jackson.databind.node.ObjectNode=#{#object.getValue()} java.lang.Boolean=#{#boolean.getRandomValue()} java.lang.CharSequence=#{#field.getName() + '_' + #shortuuid.getValue()} java.lang.Character=#{'c'} java.lang.Double=#{#decimal.getRandomValue()} java.lang.Float=#{#decimal.getRandomValue()} java.lang.Number=#{#integer.getRandomValue()} java.math.BigDecimal=#{#decimal.getRandomValue()} java.time.LocalDate=#{#datetime.getRandomValue('yyyy-MM-dd')} java.time.LocalDateTime=#{#datetime.getRandomValue('yyyy-MM-dd HH:mm:ss')} java.time.LocalTime=#{#datetime.getRandomValue('HH:mm:ss')} java.time.YearMonth=#{#datetime.getRandomValue('yyyy-MM')} java.time.ZonedDateTime=#{#datetime.getRandomValue()} java.time.temporal.Temporal=#{#temporal.getRandomValue()} java.util.AbstractMap=#{#object.getValue()} java.util.Date=#{#datetime.getRandomValue('yyyy-MM-dd HH:mm:ss')} java.util.Map=#{#object.getValue()} java.util.UUID=#{#uuid.getValue()}
Expression | Result Eg | |
---|---|---|
Camel Case(Default) | #{#field.getName()} or #{#field.getCamelCaseName()} |
testName |
Snake Case | #{#field.getSnakeCaseName()} |
test_name |
Kebab Case | #{#field.getKebabCaseName()} |
test-name |
Pascal Case | #{#field.getPascalCaseName()} |
TestName |
Snake Case Upper | #{#field.getSnakeCaseUpperName()} |
TEST_NAME |
-
完全符合 SpEL expression 标准.
-
仅当需要计算或引用时才需要使用表达式. 表达式必须以
#{
开头,以}
结尾# result {"test":"ABCD"} com.example.TestClass=ABCD
# result {"test":"ABCD_4_732f65b6b9cf"} com.example.TestClass=ABCD#{"_" + 2+2 + "_" + #shortuuid.getValue()}
-
插件有一些内置的快捷引用.请注意,不是所有引用都支持
getRandomValue()
Ref | Expression | Result Eg | Support getRandomValue() |
---|---|---|---|
#boolean |
#{#boolean.getValue()} |
false | |
#array |
#{#array.getValue()} |
[] | N |
#object |
#{#object.getValue()} |
{} | N |
#decimal |
#{#decimal.getValue()} |
0.00 | |
#integer |
#{#integer.getValue()} |
0 | |
#localdatetime |
#{#localdatetime.getValue()} |
2023-09-14 15:04:52 | |
#localdate |
#{#localdate.getValue()} |
2023-09-14 | |
#localtime |
#{#localtime.getValue()} |
15:04:52 | |
#yearmonth |
#{#yearmonth.getValue()} |
2023-09 | |
#temporal |
#{#temporal.getValue()} |
1694675092600 | |
#zoneddatetime |
#{#zoneddatetime.getValue()} |
2023-09-14T15:04:52.601+08:00 | |
#uuid |
#{#uuid.getValue()} |
679e70fa-d24b-4726-ab87-2de620333f20 | N |
#shortuuid |
#{#shortuuid.getValue()} |
732f65b6b9cf | N |
#datetime |
#{#datetime.getValue()} |
2023-09-14T15:04:52.601+08:00 |
-
自定义 Date Format
java.time.YearMonth=#{#datetime.getValue('yyyy-MM')}
or need random values
java.time.YearMonth=#{#datetime.getRandomValue('yyyy-MM')}
-
Custom Number types
# Get a random number between 0 and 100, retaining 2 decimal places. java.math.BigDecimal=#{#decimal.getRandomValue(0,100,2)}
# Get a random number between 0 and 100, retaining 2 decimal places. java.math.BigDecimal=#{#decimal.getRandomValue(2)}
-
自定义 String 类型
java.lang.CharSequence=#{#field.getName() + '_' + #shortuuid.getValue()}
or
java.lang.String=#{#field.getName() + '_' + #shortuuid.getValue()}
#field
引用比较特殊,可以简单理解为Class中的每一个字段.实际上是 PsiVariable 实例对象. -
你会发现这个配置有继承关系。所以你可以定义父类的表达式,让子类也可以收益。
com.example.ParentClass=#{#field.getName() + '_' + #shortuuid.getValue()}
class SubClass extends ParentClass { } public class Test { private SubClass subClass; }
json result:
{ "subClass": "subClass_4c672dc197e3" }
-
一些特殊情况, SpEL expressions 无法适配.
-
您无法在 Java 基础包之外创建自定义类,因为插件无法反射自定义类的实例。
You can
java.lang.Number=#{new java.math.BigDecimal(6)}
You can't
java.lang.Number=#{new com.example.BigDecimal(6)}
-
测试发现第一种情况在Kotlin中会出现问题。
Eg
java.lang.Number=#{#integer.getRandomValue}
推荐这样做
java.lang.Number=#{#integer.getRandomValue()}
-
当配置不正确导致插件无法正常运行时,可以清空配置后保存,插件将初始化默认配置。
-
想法和部分实现来自 linsage