Skip to content

Instantly share code, notes, and snippets.

@brianv0
Created December 10, 2014 22:52
Show Gist options
  • Save brianv0/f34169345b86c6fbd174 to your computer and use it in GitHub Desktop.
Save brianv0/f34169345b86c6fbd174 to your computer and use it in GitHub Desktop.
YAML provider
import java.lang.annotation.Annotation;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import javax.ws.rs.ext.*;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.cfg.PackageVersion;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
import com.fasterxml.jackson.jaxrs.base.ProviderBase;
import com.fasterxml.jackson.jaxrs.cfg.Annotations;
import com.fasterxml.jackson.jaxrs.cfg.EndpointConfigBase;
import com.fasterxml.jackson.jaxrs.cfg.MapperConfiguratorBase;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import java.util.ArrayList;
//import YamlEndpointConfig;
//import YamlMapperConfigurator;
/**
*
* @author bvan
*/
@Provider
@Consumes({"application/yaml", "text/yaml"})
@Produces({"application/yaml", "text/yaml"})
public class JacksonYamlProvider
extends ProviderBase<JacksonYamlProvider, ObjectMapper, YamlEndpointConfig, YamlMapperConfigurator> {
public static class YamlMapperConfigurator
extends MapperConfiguratorBase<YamlMapperConfigurator, ObjectMapper> {
public YamlMapperConfigurator(ObjectMapper mapper, Annotations[] defAnnotations){
super(mapper, defAnnotations);
}
/**
* Method that locates, configures and returns {@link ObjectMapper} to use
*/
@Override
public synchronized ObjectMapper getConfiguredMapper(){
/* important: should NOT call mapper(); needs to return null
* if no instance has been passed or constructed
*/
return _mapper;
}
@Override
public synchronized ObjectMapper getDefaultMapper(){
if(_defaultMapper == null){
_defaultMapper = new ObjectMapper(new YAMLFactory());
_setAnnotations(_defaultMapper, _defaultAnnotationsToUse);
}
return _defaultMapper;
}
@Override
protected ObjectMapper mapper(){
if(_mapper == null){
_mapper = new ObjectMapper(new YAMLFactory());
_setAnnotations(_mapper, _defaultAnnotationsToUse);
}
return _mapper;
}
@Override
protected AnnotationIntrospector _resolveIntrospectors(Annotations[] annotationsToUse){
// Let's ensure there are no dups there first, filter out nulls
ArrayList<AnnotationIntrospector> intr = new ArrayList<>();
for(Annotations a: annotationsToUse){
if(a != null){
intr.add(_resolveIntrospector(a));
}
}
int count = intr.size();
if(count == 0){
return AnnotationIntrospector.nopInstance();
}
AnnotationIntrospector curr = intr.get(0);
for(int i = 1, len = intr.size(); i < len; ++i){
curr = AnnotationIntrospector.pair(curr, intr.get(i));
}
return curr;
}
protected AnnotationIntrospector _resolveIntrospector(Annotations ann){
switch(ann){
case JACKSON:
return new JacksonAnnotationIntrospector();
default:
throw new IllegalStateException();
}
}
}
public static class YamlEndpointConfig
extends EndpointConfigBase<YamlEndpointConfig> {
protected YamlEndpointConfig(){
}
public static YamlEndpointConfig forReading(ObjectReader reader,
Annotation[] annotations){
return new YamlEndpointConfig()
.add(annotations, false)
.initReader(reader);
}
public static YamlEndpointConfig forWriting(ObjectWriter writer,
Annotation[] annotations){
YamlEndpointConfig config = new YamlEndpointConfig();
return config
.add(annotations, true)
.initWriter(writer);
}
@Override
public Object modifyBeforeWrite(Object value){
// nothing to add
return value;
}
}
public final static Annotations[] BASIC_ANNOTATIONS = {
Annotations.JACKSON
};
@Context
protected Providers _providers;
public JacksonYamlProvider(){
this(null, BASIC_ANNOTATIONS);
}
public JacksonYamlProvider(Annotations... annotationsToUse){
this(null, annotationsToUse);
}
public JacksonYamlProvider(ObjectMapper mapper){
this(mapper, BASIC_ANNOTATIONS);
}
public JacksonYamlProvider(ObjectMapper mapper, Annotations[] annotationsToUse){
super(new YamlMapperConfigurator(mapper, annotationsToUse));
}
@Override
public Version version(){
return PackageVersion.VERSION;
}
@Override
protected boolean hasMatchingMediaType(MediaType mediaType){
if(mediaType != null){
String subtype = mediaType.getSubtype();
return "yaml".equalsIgnoreCase(subtype) || subtype.endsWith("+yaml");
}
return false;
}
@Override
protected ObjectMapper _locateMapperViaProvider(Class<?> type, MediaType mediaType){
if(_providers != null){
ContextResolver<ObjectMapper> resolver = _providers.
getContextResolver(ObjectMapper.class, mediaType);
if(resolver == null){
resolver = _providers.getContextResolver(ObjectMapper.class, null);
}
if(resolver != null){
return resolver.getContext(type);
}
}
return null;
}
@Override
protected YamlEndpointConfig _configForReading(ObjectReader reader,
Annotation[] annotations){
return YamlEndpointConfig.forReading(reader, annotations);
}
@Override
protected YamlEndpointConfig _configForWriting(ObjectWriter writer,
Annotation[] annotations){
return YamlEndpointConfig.forWriting(writer, annotations);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment