简体   繁体   中英

Generate json schema from pojo in java - custom date type

I am using https://github.com/mbknor/mbknor-jackson-jsonSchema for generating json schema but when my object contains LocalDate, LocalDate will look like this:

   "LocalDate" : {
      "type" : "object",
      "additionalProperties" : false,
      "properties" : {
        "year" : {
          "type" : "integer"
        },
        "month" : {
          "type" : "string",
          "enum" : [ "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER" ]
        },
        "era" : {
          "$ref" : "#/definitions/Era"
        },
        "dayOfYear" : {
          "type" : "integer"
        },
        "dayOfWeek" : {
          "type" : "string",
          "enum" : [ "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY" ]
        },
        "leapYear" : {
          "type" : "boolean"
        },
        "dayOfMonth" : {
          "type" : "integer"
        },
        "monthValue" : {
          "type" : "integer"
        },
        "chronology" : {
          "$ref" : "#/definitions/IsoChronology"
        }
      },
      "required" : [ "year", "dayOfYear", "leapYear", "dayOfMonth", "monthValue" ]
    },
    "Era" : {
      "type" : "object",
      "additionalProperties" : false,
      "properties" : {
        "value" : {
          "type" : "integer"
        }
      },
      "required" : [ "value" ]
    },
    "IsoChronology" : {
      "type" : "object",
      "additionalProperties" : false,
      "properties" : {
        "calendarType" : {
          "type" : "string"
        },
        "id" : {
          "type" : "string"
        }
      }
    }

Can someone help me how can I change LocalDate type to string and also add field format which will be date?

My code is in groovy since I am writing groovy plugin:

ObjectMapper mapper = new ObjectMapper()
JsonSchemaGenerator jsonSchemaGenerator = new JsonSchemaGenerator(mapper)
JsonNode schema = jsonSchemaGenerator.generateJsonSchema(MyClass.class)

I want my LocalDate field to look like this:

    "MyField": {
      "type": "string",
      "format": "date"
    }

Thank you for any help.

You may configure a customer serializer and serialize the LocalDate inside that serializer. For example (I have copied a snippet from their github readme);

@JsonSerialize(using = MySpecialSerializer.class)
@JsonSchemaInject( json = "{\"//your schema here\"}" )
public class MyPojo {
  private LocalDate localDate;

  public LocalDate getLocalDate() {
    return localDate;
  }
  //and the rest the class
}
    public class MySpecialSerializer extends JsonSerializer<MyPojo>
    {

        @Override
        public void serialize(final MyPojo myPojo, 
                              final JsonGenerator gen, 
                              final SerializerProvider serializers) 
        throws IOException 
        {
           gen.writeObject(localDate.format(DateTimeFormatter.ISO_DATE));
           //and the other field serialization
        }

    }

You could also use jackson's java-8 date module if required.

You can tell the schema generator that you want to declare some type in the schema as if they were another type. So you can say that you want to declare each LocalDate as a String.

For that, you need to create a JsonSchemaConfig object and pass it to the JsonSchemaGenerator constructor.

In the classReMapping map you can remap types to other types.

Map<Class<?>, Class<?>> classTypeReMapping = new HashMap<>();
classTypeReMapping.put(LocalDate.class, String.class);

Optionally, in the typeToFormatMapping mapping, you can map types to format annotations. The format that you are using for LocalDate is exactly the format date as defined in the JSON schema specification:

Map<String, String> typeToFormatMapping = new HashMap<>();
typeToFormatMapping.put(LocalDate.class.getName(), "date");

Constructing a complete JsonSchemaConfig:

boolean autoGenerateTitleForProperties = false;
String defaultArrayFormat = null;
boolean useOneOfForOption = true;
boolean useOneOfForNullables = false;
boolean usePropertyOrdering = false;

boolean hidePolymorphismTypeProperty = false;
boolean disableWarnings = false;
boolean useMinLengthForNotNull = false;
boolean useTypeIdForDefinitionName = false;
boolean useMultipleEditorSelectViaProperty = false;
Set<Class<?>> uniqueItemClasses = Collections.emptySet();

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);

Map<Class<?>, Class<?>> classTypeReMapping = new HashMap<>();
classTypeReMapping.put(LocalDate.class, String.class);
// #####****##### Add remapped types here 

Map<String, String> typeToFormatMapping = new HashMap<>();
typeToFormatMapping.put(LocalDate.class.getName(), "date");
// #####****##### (optional) Add format annotations for types here 

JsonSchemaConfig config = JsonSchemaConfig.create(
        autoGenerateTitleForProperties,
        Optional.ofNullable(defaultArrayFormat),
        useOneOfForOption,
        useOneOfForNullables,
        usePropertyOrdering,
        hidePolymorphismTypeProperty,
        disableWarnings,
        useMinLengthForNotNull,
        useTypeIdForDefinitionName,
        typeToFormatMapping,
        useMultipleEditorSelectViaProperty,
        uniqueItemClasses,
        classTypeReMapping,
        Collections.emptyMap()
)

Building a JsonSchemaGenerator:

JsonSchemaGenerator jsonSchemaGenerator = new JsonSchemaGenerator(objectMapper, config);
Class<?> mainClassObject = ...;
JsonNode jsonSchema = jsonSchemaGenerator.generateJsonSchema(mainClassObject);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM