Skip to content

Latest commit

 

History

History
529 lines (399 loc) · 15.4 KB

README_ZH.md

File metadata and controls

529 lines (399 loc) · 15.4 KB

POJO to JSON

将 POJO 转换为 JSON 的简单插件

  • 支持Java中您能想到的任何类型
  • Support Java17 and last
  • 支持 Java14 Records JEP-359
  • 部分支持 Jackson 和 Fastjson 注解
  • 支持转换
    • Inner Class
    • Global Variable
    • Local Variable
    • Constructor Parameter
    • Method Parameter

Support JVM platform languages

  • Java - 完全支持
  • Kotlin - 完全支持

Usage

  • 请注意,光标的位置会影响结果!

  • 打开class文件 > 移动光标到 Class/Variable/Parameter > 右键单击 > Copy JSON > JSON 结果将复制到剪贴板 Image text

  • 打开class文件 > 移动光标到 Class/Variable/Parameter > Alt + Insert > Copy JSON > JSON 结果将复制到剪贴板 Image text

  • 项目视图选择一个class文件 > 右键单击 > Copy JSON > JSON 结果将复制到剪贴板 Image text

  • 项目视图选择多个class文件 > 右键单击 > Copy JSON > JSON 结果将生成到 Scratches 文件夹中 Image text

Installation

  • 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)

Q&A

  • 为什么使用的时候总是报错?

    This class reference level exceeds maximum limit or has nested references!
    

    当程序抛出此警告时,只有两种可能性。

    1. 这个 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":{
              ......
            }
          }
         }
       }
      }
      
    2. 当前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 :)

  • 但是如何解决这个问题呢?

    您可以尝试以下方法。

Support Annotations and Javadoc

  • @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": []
    }

Configure SpEL expression

SpEL expression 能做什么?

  • 配置有意义的测试值。

  • 字段级别控制转换结果。

  • 自定义您想要转换的任何类型。

  • IntelliJ IDEA > File > Settings > Tools > POJO to JSON Image text

Configuration

Default Configuration

  • 这是默认配置。一般情况下不需要修改。

    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()}

Random Value Configuration

  • 如果你想问之前的 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()}

Global JSON Keys Format Configuration

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

Configuration Details

  • 完全符合 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()}
    • 当配置不正确导致插件无法正常运行时,可以清空配置后保存,插件将初始化默认配置。

Contributors

想法和部分实现来自 linsage