Search code examples
javajsonspring-bootjsonschema2pojo

JSON to POJO with custom annotations


I'm trying to include Spring Boot annotations in my generated Java code from JSON like these:

@Entity
public class Person {
...
}

and

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

I'm converting from JSON to POJO with this tutorial. What can I add to my json files to make the generated Java classes include annotations @Entity and @Repository? I have yet to find a tutorial or explanation as to how to provide custom annotations.

jsonschema2pojo looks like it could work using a custom annotator when generating classes, but I am wondering if there is anything built-in to Jackson that easily allows custom annotations?


Solution

  • jsonschema2pojo's customAnnotator allowed me to add custom annotations to generated java files. The annoyance with it is that your annotator class must be in a separate project and must be included within the plugin. Here's why.

    Add the dependency to your pom.xml

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

    Add the plugin to the pom.xml plugins

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

    Create your custom annotator class in a separate project.

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

    Lastly, the json file:

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

    And the final result:

    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;
        ...
    }
    

    I wish there was a simpler way to do this.