io.swagger.util.PropertyDeserializer Maven / Gradle / Ivy
package io.swagger.util;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.DoubleNode;
import com.fasterxml.jackson.databind.node.FloatNode;
import com.fasterxml.jackson.databind.node.IntNode;
import com.fasterxml.jackson.databind.node.JsonNodeType;
import com.fasterxml.jackson.databind.node.LongNode;
import com.fasterxml.jackson.databind.node.NumericNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
import io.swagger.models.Xml;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.ObjectProperty;
import io.swagger.models.properties.Property;
import io.swagger.models.properties.PropertyBuilder;
import io.swagger.models.properties.RefProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class PropertyDeserializer extends JsonDeserializer {
Logger LOGGER = LoggerFactory.getLogger(PropertyDeserializer.class);
private static String getString(JsonNode node, PropertyBuilder.PropertyId type) {
final JsonNode detailNode = getDetailNode(node, type);
return detailNode == null ? null : detailNode.asText();
}
private static Integer getInteger(JsonNode node, PropertyBuilder.PropertyId type) {
final JsonNode detailNode = getDetailNode(node, type);
return detailNode == null ? null : detailNode.intValue();
}
private static Double getDouble(JsonNode node, PropertyBuilder.PropertyId type) {
final JsonNode detailNode = getDetailNode(node, type);
return detailNode == null ? null : detailNode.doubleValue();
}
private static BigDecimal getBigDecimal(JsonNode node, PropertyBuilder.PropertyId type) {
final JsonNode detailNode = getDetailNode(node, type);
return detailNode == null ? null : new BigDecimal(detailNode.toString());
}
private static Boolean getBoolean(JsonNode node, PropertyBuilder.PropertyId type) {
final JsonNode detailNode = getDetailNode(node, type);
return detailNode == null ? null : detailNode.booleanValue();
}
private static List getEnum(JsonNode node, PropertyBuilder.PropertyId type) {
final List result = new ArrayList();
JsonNode detailNode = getDetailNode(node, type);
if (detailNode != null) {
ArrayNode an = (ArrayNode) detailNode;
for (JsonNode child : an) {
if (child instanceof TextNode ||
child instanceof NumericNode ||
child instanceof IntNode ||
child instanceof LongNode ||
child instanceof DoubleNode ||
child instanceof FloatNode) {
result.add(child.asText());
}
}
}
return result.isEmpty() ? null : result;
}
//because of the complexity of deserializing properties we must handle vendor extensions by hand
private static Map getVendorExtensions(JsonNode node) {
Map result = new HashMap();
Iterator fieldNameIter = node.fieldNames();
while (fieldNameIter.hasNext()) {
String fieldName = fieldNameIter.next();
if(fieldName.startsWith("x-")) {
JsonNode extensionField = node.get(fieldName);
Object extensionObject = Json.mapper().convertValue(extensionField, Object.class);
result.put(fieldName, extensionObject);
}
}
return result;
}
private static List getRequired(JsonNode node, PropertyBuilder.PropertyId type) {
List result = new ArrayList();
final JsonNode detailNode = getDetailNode(node, type);
if (detailNode == null) {
return result;
}
if (detailNode.isArray()) {
ArrayNode arrayNode = (ArrayNode) detailNode;
Iterator fieldNameIter = arrayNode.iterator();
while (fieldNameIter.hasNext()) {
JsonNode item = fieldNameIter.next();
result.add(item.asText());
}
return result;
} else {
throw new RuntimeException("Required property should be a list");
}
}
private static JsonNode getDetailNode(JsonNode node, PropertyBuilder.PropertyId type) {
return node.get(type.getPropertyName());
}
@Override
public Property deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonNode node = jp.getCodec().readTree(jp);
Property property = propertyFromNode(node);
if(property != null) {
property.setXml(getXml(node));
}
return property;
}
public Xml getXml(JsonNode node) {
Xml xml = null;
if (node instanceof ObjectNode) {
ObjectNode obj = (ObjectNode) ((ObjectNode) node).get("xml");
if (obj != null) {
xml = new Xml();
JsonNode n = obj.get("name");
if (n != null) {
xml.name(n.asText());
}
n = obj.get("namespace");
if (n != null) {
xml.namespace(n.asText());
}
n = obj.get("prefix");
if (n != null) {
xml.prefix(n.asText());
}
n = obj.get("attribute");
if (n != null) {
xml.attribute(n.asBoolean());
}
n = obj.get("wrapped");
if (n != null) {
xml.wrapped(n.asBoolean());
}
}
}
return xml;
}
private Map argsFromNode(JsonNode node) {
if (node == null) return Collections.emptyMap();
final Map args = new EnumMap(PropertyBuilder.PropertyId.class);
args.put(PropertyBuilder.PropertyId.TYPE, getString(node, PropertyBuilder.PropertyId.TYPE));
args.put(PropertyBuilder.PropertyId.FORMAT, getString(node, PropertyBuilder.PropertyId.FORMAT));
args.put(PropertyBuilder.PropertyId.DESCRIPTION, getString(node, PropertyBuilder.PropertyId.DESCRIPTION));
args.put(PropertyBuilder.PropertyId.EXAMPLE, getString(node, PropertyBuilder.PropertyId.EXAMPLE));
args.put(PropertyBuilder.PropertyId.ENUM, getEnum(node, PropertyBuilder.PropertyId.ENUM));
args.put(PropertyBuilder.PropertyId.TITLE, getString(node, PropertyBuilder.PropertyId.TITLE));
args.put(PropertyBuilder.PropertyId.DEFAULT, getString(node, PropertyBuilder.PropertyId.DEFAULT));
args.put(PropertyBuilder.PropertyId.PATTERN, getString(node, PropertyBuilder.PropertyId.PATTERN));
args.put(PropertyBuilder.PropertyId.DESCRIMINATOR, getString(node, PropertyBuilder.PropertyId.DESCRIMINATOR));
args.put(PropertyBuilder.PropertyId.MIN_ITEMS, getInteger(node, PropertyBuilder.PropertyId.MIN_ITEMS));
args.put(PropertyBuilder.PropertyId.MAX_ITEMS, getInteger(node, PropertyBuilder.PropertyId.MAX_ITEMS));
args.put(PropertyBuilder.PropertyId.MIN_PROPERTIES, getInteger(node, PropertyBuilder.PropertyId.MIN_PROPERTIES));
args.put(PropertyBuilder.PropertyId.MAX_PROPERTIES, getInteger(node, PropertyBuilder.PropertyId.MAX_PROPERTIES));
args.put(PropertyBuilder.PropertyId.MIN_LENGTH, getInteger(node, PropertyBuilder.PropertyId.MIN_LENGTH));
args.put(PropertyBuilder.PropertyId.MAX_LENGTH, getInteger(node, PropertyBuilder.PropertyId.MAX_LENGTH));
args.put(PropertyBuilder.PropertyId.MINIMUM, getBigDecimal(node, PropertyBuilder.PropertyId.MINIMUM));
args.put(PropertyBuilder.PropertyId.MAXIMUM, getBigDecimal(node, PropertyBuilder.PropertyId.MAXIMUM));
args.put(PropertyBuilder.PropertyId.MULTIPLE_OF, getBigDecimal(node, PropertyBuilder.PropertyId.MULTIPLE_OF));
args.put(PropertyBuilder.PropertyId.EXCLUSIVE_MINIMUM, getBoolean(node, PropertyBuilder.PropertyId.EXCLUSIVE_MINIMUM));
args.put(PropertyBuilder.PropertyId.EXCLUSIVE_MAXIMUM, getBoolean(node, PropertyBuilder.PropertyId.EXCLUSIVE_MAXIMUM));
args.put(PropertyBuilder.PropertyId.UNIQUE_ITEMS, getBoolean(node, PropertyBuilder.PropertyId.UNIQUE_ITEMS));
args.put(PropertyBuilder.PropertyId.READ_ONLY, getBoolean(node, PropertyBuilder.PropertyId.READ_ONLY));
args.put(PropertyBuilder.PropertyId.VENDOR_EXTENSIONS, getVendorExtensions(node));
return args;
}
Property propertyFromNode(JsonNode node) {
final String type = getString(node, PropertyBuilder.PropertyId.TYPE);
final String title = getString(node, PropertyBuilder.PropertyId.TITLE);
final String format = getString(node, PropertyBuilder.PropertyId.FORMAT);
String description = getString(node, PropertyBuilder.PropertyId.DESCRIPTION);
JsonNode detailNode = node.get("$ref");
if (detailNode != null) {
return new RefProperty(detailNode.asText())
.description(description)
.title(title);
}
if (ObjectProperty.isType(type) || node.get("properties") != null) {
JsonNode example = getDetailNode(node, PropertyBuilder.PropertyId.EXAMPLE);
detailNode = node.get("additionalProperties");
if (detailNode != null && detailNode.getNodeType().equals(JsonNodeType.OBJECT)) {
Property items = propertyFromNode(detailNode);
if (items != null) {
MapProperty mapProperty = new MapProperty(items)
.description(description)
.title(title);
mapProperty.setExample(example);
mapProperty.setMinProperties(getInteger(node, PropertyBuilder.PropertyId.MIN_PROPERTIES));
mapProperty.setMaxProperties(getInteger(node, PropertyBuilder.PropertyId.MAX_PROPERTIES));
mapProperty.setVendorExtensionMap(getVendorExtensions(node));
return mapProperty;
}
} else {
detailNode = node.get("properties");
String detailNodeType = null;
Map properties = new LinkedHashMap();
if(detailNode != null){
for(Iterator> iter = detailNode.fields(); iter.hasNext();){
Map.Entry field = iter.next();
Property property = propertyFromNode(field.getValue());
if(property != null) {
properties.put(field.getKey(), property);
}
else {
if("type".equals(field.getKey()) && field.getValue() != null && "array".equals(field.getValue().asText())) {
detailNodeType = "array";
}
if(("description").equals(field.getKey()) && field.getValue().getNodeType().equals(JsonNodeType.STRING)) {
description = field.getValue().asText();
}
}
}
}
if("array".equals(detailNodeType)) {
ArrayProperty ap = new ArrayProperty()
.description(description)
.title(title);
ap.setExample(example);
PropertyBuilder.merge(ap, argsFromNode(detailNode));
ap.setDescription(description);
if(properties.keySet().size() == 1) {
String key = properties.keySet().iterator().next();
ap.setItems(properties.get(key));
}
ap.setVendorExtensionMap(getVendorExtensions(node));
return ap;
}
ObjectProperty objectProperty = new ObjectProperty(properties)
.description(description)
.title(title);
objectProperty.setExample(example);
objectProperty.setVendorExtensionMap(getVendorExtensions(node));
List required = getRequired(node, PropertyBuilder.PropertyId.REQUIRED);
objectProperty.setRequiredProperties(required);
return objectProperty;
}
}
if (ArrayProperty.isType(type)) {
detailNode = node.get("items");
if (detailNode != null) {
Property subProperty = propertyFromNode(detailNode);
ArrayProperty arrayProperty = new ArrayProperty()
.items(subProperty)
.description(description)
.title(title);
arrayProperty.setMinItems(getInteger(node, PropertyBuilder.PropertyId.MIN_ITEMS));
arrayProperty.setMaxItems(getInteger(node, PropertyBuilder.PropertyId.MAX_ITEMS));
arrayProperty.setUniqueItems(getBoolean(node, PropertyBuilder.PropertyId.UNIQUE_ITEMS));
JsonNode example = getDetailNode( node, PropertyBuilder.PropertyId.EXAMPLE);
arrayProperty.setExample(example);
arrayProperty.setVendorExtensionMap(getVendorExtensions(node));
return arrayProperty;
}
}
Map args = argsFromNode(node);
Property output = PropertyBuilder.build(type, format, args);
if (output == null) {
LOGGER.warn("no property from " + type + ", " + format + ", " + args);
return null;
}
output.setDescription(description);
return output;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy