springboot

java对象转换看这篇就够了

2021-09-30  本文已影响0人  雨中星辰0

java对象转换看这篇就够了

概述

我们在java开发过程中经常遇到对象属性拷贝的需求,总结一下,通常可以使用以下几种办法:

  1. 通过自定义编码方式
    • 优点:灵活、简单
    • 缺点:当大量不同的对象需要进行属性拷贝时,工作量大
    • 适用场景:少量的对象属性拷贝时
  2. 通过反射方式
    • 原理:通过反射方式获取对象的属性名,然后通过set方法设置对象属性
    • 优点:使用简单,可通过commons-beanutilsspring BeanUtils等工具进行转换
    • 缺点:只适合对象属性名一致时进行属性拷贝,当属性不一致时,仍需要手动处理
    • 适用场景:适合属性名称一致,但类不一致情况下进行属性拷贝
  3. 通过json方式
    • 原理:先将对象转为json字符串,再将json转为另一个类型
    • 优点:使用简单
    • 缺点:对象转换时,有一些转换逻辑时,不支持。
    • 适用场景:1. 类名不一样,但属性名一样时;2. 源类型和目标类型属性名,虽不一样,但是有对应关系时,可通过在源类型上面设置json的属性别名,进行转换。
  4. 通过mapstruct
    • 原理:在转换接口上面配置注解,mapstruct自动生成转换接口的实现。
    • 优点:基本能满足各种场景的对象转换
    • 缺点:框架较重,开发时偶尔出现,没有实时修改转换实现的情况。

示例

  1. 自定义编码

    public static OperationHistory poseidonFileToTransferHistory(PoseidonFile file){
        OperationHistory operationHistory = new OperationHistory();
        operationHistory.setExtension(file.getExtension());
        operationHistory.setFileName(file.getFileName());
        operationHistory.setFileSize(file.getFileSize());
        operationHistory.setFileType(file.getFileType());
        operationHistory.setFullPath(file.getFullPath());
        operationHistory.setFileId(file.getId());
        operationHistory.setModifyDate(new Date());
        operationHistory.setParentId(file.getParentId());
        operationHistory.setReadableSize(file.getReadableSize());
        operationHistory.setUserid(file.getUserid());
        operationHistory.setUsername(file.getUsername());
        operationHistory.setIdPath(file.getIdPath());
        operationHistory.setStorePath(file.getStorePath());
        return operationHistory;
    }
    
  2. 反射

    示例使用的是commons-beanutils。

    pom依赖:

    <dependency>
        <groupId>commons-beanutils</groupId>
        <artifactId>commons-beanutils</artifactId>
        <version>1.9.3</version>
    </dependency>
    
    

    java示例:

    public static OperationHistory poseidonFileToTransferHistory2(PoseidonFile file ) throws InvocationTargetException, IllegalAccessException {
        OperationHistory operationHistory = new OperationHistory();
        BeanUtils.copyProperties(file, operationHistory);
        return operationHistory;
    }
    
  3. json

    示例的json工具用的是gson,其他json库也类似。

    pom依赖

    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.8</version>
    </dependency>
    

    java示例:

    public static OperationHistory poseidonFileToTransferHistory3(PoseidonFile file ) throws InvocationTargetException, IllegalAccessException {
        Gson gson = new Gson();
        String json = gson.toJson(file);
        return gson.fromJson(json, OperationHistory.class);
    }
    

    gson中也可以通过@SerializedName注解对属性重命名,这样就解决了源对象属性名与目标对象属性名不一致的问题

    import com.google.gson.annotations.SerializedName;
     
    public class User {
     
        private String account;
     
        @SerializedName("code")
        private String password;
     
        private String name;
     
        private int age;
     
        public String getAccount() {
            return account;
        }
     
        public void setAccount(String account) {
            this.account = account;
        }
     
        public String getPassword() {
            return password;
        }
     
        public void setPassword(String password) {
            this.password = password;
        }
     
        public String getName() {
            return name;
        }
     
        public void setName(String name) {
            this.name = name;
        }
     
        public int getAge() {
            return age;
        }
     
        public void setAge(int age) {
            this.age = age;
        }
     
        @Override
        public String toString() {
            return "User [account=" + account + ", password=" + password + ", name=" + name + ", age=" + age + "]";
        }
     
    }
    
    1. mapstruct

      由于mapstruct转换代码是自动生成的,所以配置略显复杂。

      maven配置:

      ...
      <properties>
          <org.mapstruct.version>1.5.0.Beta1</org.mapstruct.version>
      </properties>
      ...
      <dependencies>
          <dependency>
              <groupId>org.mapstruct</groupId>
              <artifactId>mapstruct</artifactId>
              <version>${org.mapstruct.version}</version>
          </dependency>
      </dependencies>
      ...
      <build>
          <plugins>
              <plugin>
                  <groupId>org.apache.maven.plugins</groupId>
                  <artifactId>maven-compiler-plugin</artifactId>
                  <version>3.8.1</version>
                  <configuration>
                      <source>1.8</source>
                      <target>1.8</target>
                      <annotationProcessorPaths>
                          <path>
                              <groupId>org.mapstruct</groupId>
                              <artifactId>mapstruct-processor</artifactId>
                              <version>${org.mapstruct.version}</version>
                          </path>
                      </annotationProcessorPaths>
                  </configuration>
              </plugin>
          </plugins>
      </build>
      ...
      

      idea配置:

      IntelliJ IDEA中安装MapStruct Support插件:File -> Settings -> Plugins 搜索 MapStruct support 安装,同时File -> Settings -> Compiler -> Annotation Processors 勾选“Enable annotation processing”

      还要确保您的项目使用的是 Java 1.8 或更高版本(项目属性→“Java 编译器”→“编译合规性级别”)。它不适用于旧版本。

      java示例:

      import org.mapstruct.Mapper;
      
      import org.mapstruct.Mapper;
      import org.mapstruct.Mapping;
      import org.mapstruct.Mappings;
      @Mapper
      public interface CarMapper {
          CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );
            
            //当源类型与目标类型属性名不一致时
          @Mapping(target = "manufacturer", source = "make")
          @Mapping(target = "seatCount", source = "numberOfSeats")
          CarDto carToCarDto(Car car);
            
            //当源类型与目标类型属性名一致时
          @Mappings({})
          PersonDto personToPersonDto(Person person);
          
          @Override
          @Mappings({
          //当对象属性转换有一些规则时,可调用java方法进行转换,注意:这里的参数名应为方法定义时的参数名一致
          @Mapping(target = "service", expression = "java(toService(entity))"),
          @Mapping(target = "mocks", expression = "java(toMocks(entity))"),
          @Mapping(target = "params", expression = "java(toRule(entity))"),
          //当对象的属性需要依赖其他属性转换完后才能转换,可以使用dependsOn进行配置
          @Mapping(target = "url", dependsOn = {"service", "params"}, expression = "java(dto2URL(demotionDTO).toFullString())")})
          DemotionDTO update2DTO(DemotionUpdateParam entity);
          
         default String toService(DemotionUpdateParam entity) {
         return StringUtils.isEmpty(entity.getGroup()) ? entity.getServiceInf() : entity.getGroup() + "/" + entity.getServiceInf();
          }
          
         default Map<String, String> toMocks(DemotionUpdateParam entity) {
         return entity.getMocks()
            .stream()
            .filter(i -> StringUtils.split(i, "=").length > 1)
            .collect(Collectors.toMap(
                    i -> i.split("=")[0],
                    i -> i.split("=")[1]
                    )
            );
          }
          
         default String toRule(DemotionUpdateParam entity) {
         Map<String, String> map = toMocks(entity);
         return map.keySet().stream()
            .map(i -> i + "=" + URL.encode(map.get(i)))
            .collect(Collectors.joining("&"));
         }
      }
      
上一篇下一篇

猜你喜欢

热点阅读