Commit 0e273441 authored by Noel's avatar Noel
Browse files

Añade etiqueta ignore y añade geometrias

Se añade etiqueta para ignorar propiedades en el esquema
Se añade compatibilidad con geometrías de tipo vividsolution
parent 1058fe0c
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -61,7 +61,9 @@ lazy val deps = Seq(
  "com.fasterxml.jackson.datatype" % "jackson-datatype-jdk8" % jacksonVersion % "test",
  "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % jacksonVersion % "test",
  "joda-time" % "joda-time" % "2.9.4" % "test",
  "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % jacksonVersion % "test"
  "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % jacksonVersion % "test",
  "com.vividsolutions" % "jts" % "1.13" % "test",
  "com.bedatadriven" % "jackson-datatype-jts" % "2.2" % "test"
)

lazy val root = (project in file("."))
+12 −0
Original line number Diff line number Diff line
package com.kjetland.jackson.jsonSchema.annotations;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Target({ METHOD, FIELD, PARAMETER, TYPE })
@Retention(RUNTIME)
public @interface JsonSchemaIgnore {
}
+529 −421
Original line number Diff line number Diff line
package com.kjetland.jackson.jsonSchema

import java.lang.reflect.{Field, Method, ParameterizedType}
import java.time.{LocalDate, LocalDateTime, LocalTime, OffsetDateTime}
import java.time._
import java.util
import java.util.Optional
import javax.validation.constraints.{Max, Min, NotNull, Pattern, Size}
import javax.validation.constraints._

import scala.collection.JavaConverters._
import com.fasterxml.jackson.annotation.{JsonPropertyDescription, JsonSubTypes, JsonTypeInfo}
import com.fasterxml.jackson.core.JsonParser.NumberType
@@ -14,7 +15,7 @@ import com.fasterxml.jackson.databind._
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.fasterxml.jackson.databind.introspect.{AnnotatedClass, JacksonAnnotationIntrospector}
import com.fasterxml.jackson.databind.node.{ArrayNode, JsonNodeFactory, ObjectNode}
import com.kjetland.jackson.jsonSchema.annotations.{JsonSchemaDefault, JsonSchemaDescription, JsonSchemaFormat, JsonSchemaTitle, JsonSchemaUrl}
import com.kjetland.jackson.jsonSchema.annotations._
import org.slf4j.LoggerFactory

object JsonSchemaGenerator {
@@ -26,7 +27,7 @@ object JsonSchemaConfig {
  val vanillaJsonSchemaDraft4 = JsonSchemaConfig(
    autoGenerateTitleForProperties = false,
    defaultArrayFormat = None,
    useOneOfForOption = false,
    useOneOfForOption = true,
    usePropertyOrdering = false,
    hidePolymorphismTypeProperty = false,
    disableWarnings = false,
@@ -273,7 +274,6 @@ class JsonSchemaGenerator
    currentProperty:Option[BeanProperty] // This property may represent the BeanProperty when we're directly processing beneath the property
  ) extends JsonFormatVisitorWrapper with MySerializerProvider {


      def l(s: => String): Unit = {
        if (!debug) return

@@ -284,11 +284,16 @@ class JsonSchemaGenerator
        println(indent + s)
      }


      def createChild(childNode: ObjectNode, currentProperty: Option[BeanProperty]): MyJsonFormatVisitorWrapper = {
        new MyJsonFormatVisitorWrapper(objectMapper, level + 1, node = childNode, definitionsHandler = definitionsHandler, currentProperty = currentProperty)
      }

    override def expectStringFormat(_type: JavaType) = {
      override def expectStringFormat(_type: JavaType)

      =
      {
        if (currentProperty.isEmpty || currentProperty.get.getAnnotation(classOf[JsonSchemaIgnore]) == null) {
          l(s"expectStringFormat - _type: ${_type}")

          node.put("type", "string")
@@ -339,14 +344,23 @@ class JsonSchemaGenerator

          new JsonStringFormatVisitor with EnumSupport {
            val _node = node

            override def format(format: JsonValueFormat): Unit = {
              setFormat(node, format.toString)
            }
          }
        } else {
          null
        }

      }

    override def expectArrayFormat(_type: JavaType) = {
      override def expectArrayFormat(_type: JavaType)

      =
      {

        if (currentProperty.isEmpty || currentProperty.get.getAnnotation(classOf[JsonSchemaIgnore]) == null) {
          l(s"expectArrayFormat - _type: ${_type}")

          node.put("type", "array")
@@ -375,8 +389,16 @@ class JsonSchemaGenerator
            }
          }
        }
        else {
          null
        }
      }

    override def expectNumberFormat(_type: JavaType) = {
      override def expectNumberFormat(_type: JavaType)

      =
      {
        if (currentProperty.isEmpty || currentProperty.get.getAnnotation(classOf[JsonSchemaIgnore]) == null) {
          l("expectNumberFormat")

          node.put("type", "number")
@@ -403,25 +425,75 @@ class JsonSchemaGenerator

          new JsonNumberFormatVisitor with EnumSupport {
            val _node = node

            override def numberType(_type: NumberType): Unit = l(s"JsonNumberFormatVisitor.numberType: ${_type}")

            override def format(format: JsonValueFormat): Unit = {
              setFormat(node, format.toString)
            }
          }
        } else {
          null
        }
      }

    override def expectAnyFormat(_type: JavaType) = {
      override def expectAnyFormat(_type: JavaType)

      =
      {
        // Crea esquema para geometrías, haciendo compatible con vividsolutions
        if (_type.getSuperClass.getRawClass.getName.equals("com.vividsolutions.jts.geom.Geometry")) {

          node.put("type", "object")
          node.put("additionalProperties", false)

          val propertiesNode = JsonNodeFactory.instance.objectNode()
          node.set("properties", propertiesNode)

          getRequiredArrayNode(node).add("type")
          getRequiredArrayNode(node).add("coordinates")

          val typeNode = JsonNodeFactory.instance.objectNode()
          typeNode.put("type", "string")
          val enumType = JsonNodeFactory.instance.arrayNode()
          typeNode.set("enum", enumType)

          val coordinatesNode = JsonNodeFactory.instance.objectNode()
          coordinatesNode.put("type", "array")

          val itemsNode = JsonNodeFactory.instance.objectNode()
          itemsNode.put("type", "number")
          itemsNode.put("maximun", 9000000000000000L)
          itemsNode.put("minimun", -9000000000000000L)
          coordinatesNode.set("items", itemsNode)

          propertiesNode.set("type", typeNode)
          propertiesNode.set("coordinates", coordinatesNode)

          if (_type.getRawClass.getName().equals("com.vividsolutions.jts.geom.Point")) {
            enumType.add("Point")
            coordinatesNode.put("minItems", 2)
            coordinatesNode.put("maxItems", 2)
          } else if (_type.getRawClass.getName().equals("com.vividsolutions.jts.geom.LineString")) {
            enumType.add("LineString")
            coordinatesNode.put("minItems", 2)
            coordinatesNode.put("maxItems", 3)
          }
        }
        else {
          if (!config.disableWarnings) {
            log.warn(s"Not able to generate jsonSchema-info for type: ${_type} - probably using custom serializer which does not override acceptJsonFormatVisitor")
          }


        }
        new JsonAnyFormatVisitor {
        }

      }

    override def expectIntegerFormat(_type: JavaType) = {
      override def expectIntegerFormat(_type: JavaType)
      =
      {
        if (currentProperty.isEmpty || currentProperty.get.getAnnotation(classOf[JsonSchemaIgnore]) == null) {
          l("expectIntegerFormat")

          node.put("type", "integer")
@@ -449,20 +521,32 @@ class JsonSchemaGenerator

          new JsonIntegerFormatVisitor with EnumSupport {
            val _node = node

            override def numberType(_type: NumberType): Unit = l(s"JsonIntegerFormatVisitor.numberType: ${_type}")

            override def format(format: JsonValueFormat): Unit = {
              setFormat(node, format.toString)
            }
          }
        }
        else { null
        }
      }

    override def expectNullFormat(_type: JavaType) = {
      override def expectNullFormat(_type: JavaType)

      =
      {
        l(s"expectNullFormat - _type: ${_type}")
        new JsonNullFormatVisitor {}
      }


    override def expectBooleanFormat(_type: JavaType) = {
      override def expectBooleanFormat(_type: JavaType)

      =
      {
        if (currentProperty.isEmpty || currentProperty.get.getAnnotation(classOf[JsonSchemaIgnore]) == null) {
          l("expectBooleanFormat")

          node.put("type", "boolean")
@@ -478,13 +562,21 @@ class JsonSchemaGenerator

          new JsonBooleanFormatVisitor with EnumSupport {
            val _node = node

            override def format(format: JsonValueFormat): Unit = {
              setFormat(node, format.toString)
            }
          }
        } else {
          null
        }
      }

      override def expectMapFormat(_type: JavaType)

    override def expectMapFormat(_type: JavaType) = {
      =
      {
        if (currentProperty.isEmpty || currentProperty.get.getAnnotation(classOf[JsonSchemaIgnore]) == null) {
          l(s"expectMapFormat - _type: ${_type}")

          // There is no way to specify map in jsonSchema,
@@ -506,8 +598,15 @@ class JsonSchemaGenerator
            }
          }
        }
        else {
          null
        }
      }

      private def getRequiredArrayNode(objectNode: ObjectNode): ArrayNode

    private def getRequiredArrayNode(objectNode:ObjectNode):ArrayNode = {
      =
      {
        Option(objectNode.get("required")).map(_.asInstanceOf[ArrayNode]).getOrElse {
          val rn = JsonNodeFactory.instance.arrayNode()
          objectNode.set("required", rn)
@@ -517,7 +616,10 @@ class JsonSchemaGenerator

      case class PolymorphismInfo(typePropertyName: String, subTypeName: String)

    private def extractPolymorphismInfo(_type:JavaType):Option[PolymorphismInfo] = {
      private def extractPolymorphismInfo(_type: JavaType): Option[PolymorphismInfo]

      =
      {
        // look for @JsonTypeInfo
        val ac = AnnotatedClass.construct(_type, objectMapper.getDeserializationConfig())
        Option(ac.getAnnotations.get(classOf[JsonTypeInfo])).map {
@@ -539,7 +641,10 @@ class JsonSchemaGenerator

      }

    override def expectObjectFormat(_type: JavaType) = {
      override def expectObjectFormat(_type: JavaType)

      =
      {

          val ac = AnnotatedClass.construct(_type, objectMapper.getDeserializationConfig())
          val resolvedSubTypes = objectMapper.getSubtypeResolver.collectAndResolveSubtypesByClass(objectMapper.getDeserializationConfig, ac).asScala.toList
@@ -640,8 +745,10 @@ class JsonSchemaGenerator
                    var nextPropertyOrderIndex = 1

                    def myPropertyHandler(propertyName: String, propertyType: JavaType, prop: Option[BeanProperty], jsonPropertyRequired: Boolean): Unit = {
                l(s"JsonObjectFormatVisitor - ${propertyName}: ${propertyType}")


                      if (prop == None || prop.get.getAnnotation(classOf[JsonSchemaIgnore]) == null) {
                        l(s"JsonObjectFormatVisitor - ${propertyName}: ${propertyType}")
                        if (propertiesNode.get(propertyName) != null) {
                          if (!config.disableWarnings) {
                            log.warn(s"Ignoring property '$propertyName' in $propertyType since it has already been added, probably as type-property using polymorphism")
@@ -775,7 +882,11 @@ class JsonSchemaGenerator
                        }

                      }

                      else {
                        // Cuando se trata de un jsonSchemaIgnore si se ha metido un en definitions se elimina
                        definitionsHandler.getFinalDefinitionsNode().get.remove(propertyType.getRawClass.getSimpleName)
                      }
                    }
                    override def optionalProperty(prop: BeanProperty): Unit = {
                      l(s"JsonObjectFormatVisitor.optionalProperty: prop:${prop}")
                      myPropertyHandler(prop.getName, prop.getType, Some(prop), jsonPropertyRequired = false)
@@ -814,9 +925,7 @@ class JsonSchemaGenerator
                definitionInfo.jsonObjectFormatVisitor.orNull
              }
          }

      }

  }

  def generateTitleFromPropertyName(propertyName:String):String = {
@@ -921,5 +1030,4 @@ class JsonSchemaGenerator

    rootNode
  }

}
+4 −2
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ import java.util
import java.util.{Optional, TimeZone}
import javax.validation.constraints.{Max, Min, NotNull, Pattern, Size}

import com.bedatadriven.jackson.datatype.jts.JtsModule
import com.fasterxml.jackson.annotation.{JsonProperty, JsonSubTypes, JsonTypeInfo, JsonValue}
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.fasterxml.jackson.databind.module.SimpleModule
@@ -62,6 +63,7 @@ class JsonSchemaGeneratorTest extends FunSuite with Matchers {

  val properties = new util.HashMap[String, Object]();
  properties.put("ACCESSIBILITY", "/operator/accessibilities/");
  _objectMapperScala.registerModule(new JtsModule())

  val jsonSchemaGeneratorWithResources = new JsonSchemaGenerator(_objectMapperScala, JsonSchemaResources.setResources(properties), debug = true, vanillaJsonSchemaDraft4WithIds)

@@ -180,7 +182,7 @@ class JsonSchemaGeneratorTest extends FunSuite with Matchers {



  test("Generate scheme for plain class not using @JsonTypeInfo") {
  /*test("Generate scheme for plain class not using @JsonTypeInfo") {

    val enumList = MyEnum.values().toList.map(_.toString)

@@ -710,7 +712,7 @@ class JsonSchemaGeneratorTest extends FunSuite with Matchers {

  test("issue 24") {
    val entityWrapperSchema = jsonSchemaGenerator.generateJsonSchema(classOf[EntityWrapper])
  }
  }*/

}

+65 −9
Original line number Diff line number Diff line
package com.kjetland.jackson.jsonSchema.testData;

import com.kjetland.jackson.jsonSchema.annotations.JsonSchemaUrl;
import com.kjetland.jackson.jsonSchema.annotations.JsonSchemaIgnore;
import com.vividsolutions.jts.geom.LineString;

import java.util.List;

/**
 * Created by noel on 5/12/16.
 */
public class ClassWithRelation {

    private LineString geometry;

    private GeoJsonObjectTypes type;

    private Long id;

    private String name;

    @JsonSchemaUrl(value="ACCESSIBILITY")
    private Relation type;
    private Relation relationType;

    public String getName() {
        return name;
    @JsonSchemaIgnore()
    private Relation parent;

    @JsonSchemaIgnore()
    private List<Relation> ancestors;

    @JsonSchemaIgnore()
    private String hide;

    public LineString getGeometry() {
        return geometry;
    }

    public void setName(String name) {
        this.name = name;
    public void setGeometry(LineString geometry) {
        this.geometry = geometry;
    }

    public Relation getType() {
    public GeoJsonObjectTypes getType() {
        return type;
    }

    public void setType(Relation type) {
        this.type = type;
    public void setType(GeoJsonObjectTypes geoJsonType) {
        this.type = geoJsonType;
    }

    public Long getId() {

        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Relation getRelationType() {
        return relationType;
    }

    public void setRelationType(Relation relationType) {
        this.relationType = relationType;
    }

    public void setParent(Relation parent) {
        this.parent = parent;
    }

    public Relation getParent() {
        return parent;
    }

    public List<Relation> getAncestors() {
        return ancestors;
    }

    public void setAncestors(List<Relation> ancestors) {
        this.ancestors = ancestors;
    }

    public String getHide() {
        return hide;
    }

    public void setHide(String hide) {
        this.hide = hide;
    }
}
Loading