使用自定义注释将JSON转换为POJO

10

我正在尝试将类似这样的Spring Boot注解包含在由JSON生成的Java代码中:

@Entity
public class Person {
...
}
@Repository
public interface PersonRepository extends CrudRepository<Person, Long> 
{
}

我正在使用这个教程将JSON转换为POJO。我该在我的JSON文件中添加什么以使生成的Java类包括注释@Entity和@Repository?我还没有找到有关如何提供自定义注释的教程或解释。

jsonschema2pojo看起来可以使用自定义注释器来生成类,但我想知道是否有任何内置于Jackson中的东西可轻松允许自定义注释?


你教程中提到的插件将JSON Schema转换为POJO。JSON Schema不是JSON。 - DwB
@DwB jsonschema2pojo 允许您指定源类型为 JSON 或 JSONSchema。对我来说,它是 JSON 还是 JSON Schema 并不重要,只要我能获得带有 Hibernate 注释的生成 POJO 就可以了。 - Gaʀʀʏ
您可以使用以下在线工具将JSON转换为POJO https://www.workversatile.com/json-to-pojo - Arshad Shaikh
3个回答

12

jsonschema2pojo的customAnnotator允许我向生成的Java文件中添加自定义注释。但它的烦恼在于,你的注释器类必须在一个单独的项目中,并且必须包含在插件中。这是为什么,请看这里

将依赖项添加到您的pom.xml中。

<dependency>
    <groupId>org.jsonschema2pojo</groupId>
    <artifactId>jsonschema2pojo-core</artifactId>
    <version>0.4.0</version>
</dependency>

将插件添加到pom.xml的插件中

<plugin>
    <groupId>org.jsonschema2pojo</groupId>
    <artifactId>jsonschema2pojo-maven-plugin</artifactId>
    <version>0.5.1</version>
    <dependencies>
        <!-- NOTE: Your annotator MUST come from a dependency -->
        <dependency>
            <groupId>ANNOTATOR_GROUP_ID</groupId>
            <artifactId>ANNOTATOR_ARTIFACT</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <scope>compile</scope>
            <version>1.5.2.RELEASE</version>
        </dependency>
       <!-- NOTE: Any annotation used must have its dependency here!!! -->
    </dependencies>
    <configuration>
        <sourceDirectory>${basedir}/src/main/resources/schema</sourceDirectory>
        <targetPackage>com.test.gen</targetPackage>
        <useCommonsLang3>true</useCommonsLang3>
        <customAnnotator>com.fully.qualified.path.YourAnnotator</customAnnotator>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
        </execution>
    </executions>
</plugin>

单独的项目中创建自定义注释器类。

package com.deere.gtin_k.pdeaas.work_manager.application;

import com.fasterxml.jackson.databind.JsonNode;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JFieldVar;
import org.jsonschema2pojo.AbstractAnnotator;

import javax.persistence.Entity;

public class HibernateAnnotator extends AbstractAnnotator {

    @Override
    public void propertyField(JFieldVar field, JDefinedClass clazz, String propertyName, JsonNode propertyNode) {
        super.propertyField(field, clazz, propertyName, propertyNode);

        // Note: does not have to be the propertyName, could be the field or propertyNode that is verified.
        if (propertyName.equals("entity")) {
            clazz.annotate(Entity.class);
        }
    }
}

最后是json文件:

{
  "title": "Person",
  "type": "object",
  "properties": {
    "entity": true,
    "name": {
      "type": "string"
    }
  }
}

最终结果:

package com.test.gen;

import java.util.HashMap;
import java.util.Map;
import javax.persistence.Entity;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;


/**
 * Person
 * <p>
 * 
 * 
 */
@JsonInclude(JsonInclude.Include.NON_NULL)
@Entity
@JsonPropertyOrder({
    "entity",
    "name"
})
public class Person {

    @JsonProperty("entity")
    private Object entity;
    ...
}

我希望有一种更简单的方法来做这件事。


1
对于任何想要更多控制的人,您可以使用minimal-jsonjavapoet编写自己的JSON->Java解析。 - Gaʀʀʏ
你可以使用多个 <customAnnotator>com.fully.qualified.path.YourAnnotator</customAnnotator> 吗? - Marco Dalla Santa
我尝试添加它们。它没有给出任何错误,但似乎只接受最后一个。 - adbdkb
@Gaʀʀʏ,你能给我展示一下示例项目吗? - edhi.uchiha

3
在我的情况下,我需要添加@ValueOfEnum(enumClass = com.mycompany.SampleType),如在https://www.baeldung.com/javax-validations-enums(第5个选项)中建议的那样。
所以我修改了覆盖方法。
@Override
public void propertyField(JFieldVar field, JDefinedClass clazz, String propertyName, JsonNode propertyNode) {
    super.propertyField(field, clazz, propertyName, propertyNode);

    if (propertyNode.get("enumClass") != null) {
        try {
            field.annotate(ValueOfEnum.class).param("enumClass",  Class.forName(propertyNode.get("enumClass").asText()));
        } catch (ClassNotFoundException e) {
            System.err.println("'Not able to add @ValueOfEnum(enumClass = " + propertyNode.get("enumClass").asText() + "' annotation to property :" + propertyName + ". Enum not found in the classpath");
        }
    }
}

同时确保 ValueOfEnum 和实际枚举类型对于插件是可用的,在 pom.xml 文件中添加插件依赖。


0

注解装饰的替代方案

我猜测问题的意图是:

  • 您有从JSON模式生成的POJO
  • 您想使用ORM(JPA)将POJO管理为实体
  • 您想使用Spring Data与JPA实体

也许一个替代尝试用JPA注解装饰生成的POJO的方法是使用orm.xml。这可以用于定义实体并作为替代方法与ORM集成,而不是对POJO进行注释。这对于无法自己进行更改的现有类可能很有用,或者在这种情况下代码是生成的。

使用生成的POJO,将orm.xml添加到${project.basedir}/src/main/resources/META-INF中,而不是添加注释

也许像这样:

orm.xml

<?xml version="1.0" encoding="UTF-8" ?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_2_0.xsd"
                 version="2.0">

    <entity class="com.test.gen.Person" access="FIELD">
        <table name="person"/>
        <attributes>
            <id name="id">
                <generated-value strategy="AUTO"/>
            </id>
            <basic name="firstname">
                <column name="firstname" length="200"/>
            </basic>
        </attributes>
    </entity>

</entity-mappings>

你不能使用 orm 文件完成所有任务。@BatchSize/@FetchMode 不起作用。 - Geek Junior

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接