Skip to content

Instantly share code, notes, and snippets.

Created July 31, 2014 00:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/a14d642df11c54ee8495 to your computer and use it in GitHub Desktop.
Save anonymous/a14d642df11c54ee8495 to your computer and use it in GitHub Desktop.
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonArrayFormatVisitor;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatTypes;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitable;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor;
import com.fasterxml.jackson.module.jsonSchema.JsonSchema;
import com.fasterxml.jackson.module.jsonSchema.factories.*;
import com.fasterxml.jackson.module.jsonSchema.types.ArraySchema;
import com.fasterxml.jackson.module.jsonSchema.types.ObjectSchema;
import java.util.List;
/**
* When visiting properties that are Models, include a $ref property
* indicating the model class, and don't visit any deeper.
*/
public class CustomSchemaFactoryWrapper extends SchemaFactoryWrapper {
CustomSchemaFactoryWrapper() {
this(null);
}
CustomSchemaFactoryWrapper(SerializerProvider p) {
super(p);
this.visitorFactory = new MyFormatVisitorFactory();
}
protected String getModelRef(Class modelClass) {
return "#" + modelClass.getSimpleName();
}
private class MyArrayVisitor extends ArrayVisitor {
public MyArrayVisitor(SerializerProvider provider, ArraySchema arraySchema) {
super(provider, arraySchema);
}
@Override
public void itemsFormat(JsonFormatVisitable handler, JavaType contentType) throws JsonMappingException {
if (isModel(contentType)) {
JsonSchema propSchema = new ObjectSchema();
propSchema.set$ref(getModelRef(contentType.getRawClass()));
schema.setItemsSchema(propSchema);
} else {
super.itemsFormat(handler, contentType);
}
}
@Override
public void itemsFormat(JsonFormatTypes format) throws JsonMappingException {
schema.setItemsSchema(JsonSchema.minimalForFormat(format));
}
}
private static class MyObjectVisitor extends ObjectVisitor {
public MyObjectVisitor(SerializerProvider provider, ObjectSchema schema) {
super(provider, schema);
}
@Override
public void optionalProperty(String name, JsonFormatVisitable handler, JavaType propertyTypeHint) throws JsonMappingException {
schema.putOptionalProperty(name, propertySchema(handler, propertyTypeHint));
}
@Override
public void optionalProperty(BeanProperty writer) throws JsonMappingException {
JavaType type = writer.getType();
if (isModel(type)) {
JsonSchema propSchema = new ObjectSchema();
propSchema.setRequired(false);
propSchema.set$ref(type.getRawClass().getName());
schema.putProperty(writer.getName(), propSchema);
return;
}
schema.putOptionalProperty(writer.getName(), propertySchema(writer));
}
@Override
public void property(BeanProperty writer) throws JsonMappingException {
schema.putProperty(writer.getName(), propertySchema(writer));
}
}
public static boolean isModel(JavaType type) {
return type.getRawClass() != String.class
&& !isBoxedPrimitive(type)
&& !type.isPrimitive()
&& !type.isMapLikeType()
&& !type.isCollectionLikeType();
}
private static boolean isBoxedPrimitive(JavaType type) {
return type.getRawClass() == Boolean.class
|| type.getRawClass() == Byte.class
|| type.getRawClass() == Long.class
|| type.getRawClass() == Integer.class
|| type.getRawClass() == Short.class
|| type.getRawClass() == Float.class
|| type.getRawClass() == Double.class;
}
public class MyFormatVisitorFactory extends FormatVisitorFactory {
@Override
public JsonObjectFormatVisitor objectFormatVisitor(SerializerProvider provider, ObjectSchema objectSchema) {
MyObjectVisitor visitor = new MyObjectVisitor(provider, objectSchema);
visitor.setWrapperFactory(new WrapperFactory() {
public SchemaFactoryWrapper getWrapper(SerializerProvider provider) {
SchemaFactoryWrapper wrapper = new CustomSchemaFactoryWrapper();
wrapper.setProvider(getProvider());
return wrapper;
}
});
return visitor;
}
@Override
public JsonArrayFormatVisitor arrayFormatVisitor(SerializerProvider provider, ArraySchema arraySchema) {
return new MyArrayVisitor(provider, arraySchema);
}
}
public static class Animal {
public String species;
}
public static class Zoo {
public String name;
public List<Animal> animals;
}
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
Class generateSchemaFor = Zoo.class;
SchemaFactoryWrapper visitor = new CustomSchemaFactoryWrapper();
objectMapper.acceptJsonFormatVisitor(objectMapper.constructType(generateSchemaFor), visitor);
JsonSchema jsonSchema = visitor.finalSchema();
System.out.println(objectMapper.writeValueAsString(jsonSchema));
}
}
@dnault
Copy link

dnault commented Mar 12, 2016

This works with Jackson 2.4.3. For Jackson 2.6 and later, see https://gist.github.com/dnault/3b2f3b14be8bba76da81

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment