added bigDecimalAsString option to allow serializing with strings

This commit is contained in:
Tony Tam 2015-12-30 12:32:37 -08:00
parent ac7856d009
commit 1cd54ee685
7 changed files with 68 additions and 32 deletions

View File

@ -109,6 +109,10 @@ public interface CodegenConfig {
Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs); Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs);
void postProcessModelProperty(CodegenModel model, CodegenProperty property);
void postProcessParameter(CodegenParameter parameter);
String apiFilename(String templateName, String tag); String apiFilename(String templateName, String tag);
boolean shouldOverwrite(String filename); boolean shouldOverwrite(String filename);

View File

@ -34,6 +34,9 @@ public class CodegenConstants {
public static final String SERIALIZABLE_MODEL = "serializableModel"; public static final String SERIALIZABLE_MODEL = "serializableModel";
public static final String SERIALIZABLE_MODEL_DESC = "boolean - toggle \"implements Serializable\" for generated models"; public static final String SERIALIZABLE_MODEL_DESC = "boolean - toggle \"implements Serializable\" for generated models";
public static final String SERIALIZE_BIG_DECIMAL_AS_STRING = "bigDecimalAsString";
public static final String SERIALIZE_BIG_DECIMAL_AS_STRING_DESC = "boolean - treat BigDecimal values as Strings to avoid precision loss. Default: false";
public static final String LIBRARY = "library"; public static final String LIBRARY = "library";
public static final String LIBRARY_DESC = "library template (sub-template)"; public static final String LIBRARY_DESC = "library template (sub-template)";

View File

@ -120,6 +120,12 @@ public class DefaultCodegen {
return objs; return objs;
} }
// override to post-process any model properties
public void postProcessModelProperty(CodegenModel model, CodegenProperty property){}
// override to post-process any parameters
public void postProcessParameter(CodegenParameter parameter){}
//override with any special handling of the entire swagger spec //override with any special handling of the entire swagger spec
public void preprocessSwagger(Swagger swagger) { public void preprocessSwagger(Swagger swagger) {
} }
@ -620,7 +626,9 @@ public class DefaultCodegen {
**/ **/
public String getSwaggerType(Property p) { public String getSwaggerType(Property p) {
String datatype = null; String datatype = null;
if (p instanceof StringProperty) { if (p instanceof StringProperty && "number".equals(p.getFormat())) {
datatype = "BigDecimal";
} else if (p instanceof StringProperty) {
datatype = "string"; datatype = "string";
} else if (p instanceof ByteArrayProperty) { } else if (p instanceof ByteArrayProperty) {
datatype = "ByteArray"; datatype = "ByteArray";
@ -843,6 +851,12 @@ public class DefaultCodegen {
} }
addVars(m, impl.getProperties(), impl.getRequired()); addVars(m, impl.getProperties(), impl.getRequired());
} }
if(m.vars != null) {
for(CodegenProperty prop : m.vars) {
postProcessModelProperty(m, prop);
}
}
return m; return m;
} }
@ -1595,6 +1609,8 @@ public class DefaultCodegen {
} }
p.paramName = toParamName(bp.getName()); p.paramName = toParamName(bp.getName());
} }
postProcessParameter(p);
return p; return p;
} }

View File

@ -1,45 +1,21 @@
package io.swagger.codegen.languages; package io.swagger.codegen.languages;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import io.swagger.codegen.CliOption; import io.swagger.codegen.*;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile;
import io.swagger.models.Model; import io.swagger.models.Model;
import io.swagger.models.Operation; import io.swagger.models.Operation;
import io.swagger.models.Path; import io.swagger.models.Path;
import io.swagger.models.Swagger; import io.swagger.models.Swagger;
import io.swagger.models.parameters.BodyParameter;
import io.swagger.models.parameters.FormParameter; import io.swagger.models.parameters.FormParameter;
import io.swagger.models.parameters.Parameter; import io.swagger.models.parameters.Parameter;
import io.swagger.models.properties.ArrayProperty; import io.swagger.models.properties.*;
import io.swagger.models.properties.BooleanProperty;
import io.swagger.models.properties.DoubleProperty;
import io.swagger.models.properties.FloatProperty;
import io.swagger.models.properties.IntegerProperty;
import io.swagger.models.properties.LongProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import io.swagger.models.properties.StringProperty;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.*;
public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(JavaClientCodegen.class); private static final Logger LOGGER = LoggerFactory.getLogger(JavaClientCodegen.class);
public static final String FULL_JAVA_UTIL = "fullJavaUtil"; public static final String FULL_JAVA_UTIL = "fullJavaUtil";
@ -55,6 +31,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
protected boolean fullJavaUtil = false; protected boolean fullJavaUtil = false;
protected String javaUtilPrefix = ""; protected String javaUtilPrefix = "";
protected Boolean serializableModel = false; protected Boolean serializableModel = false;
protected boolean serializeBigDecimalAsString = false;
public JavaClientCodegen() { public JavaClientCodegen() {
super(); super();
@ -101,6 +78,8 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
cliOptions.add(new CliOption(CodegenConstants.LOCAL_VARIABLE_PREFIX, CodegenConstants.LOCAL_VARIABLE_PREFIX_DESC)); cliOptions.add(new CliOption(CodegenConstants.LOCAL_VARIABLE_PREFIX, CodegenConstants.LOCAL_VARIABLE_PREFIX_DESC));
cliOptions.add(new CliOption(CodegenConstants.SERIALIZABLE_MODEL, CodegenConstants.SERIALIZABLE_MODEL_DESC, cliOptions.add(new CliOption(CodegenConstants.SERIALIZABLE_MODEL, CodegenConstants.SERIALIZABLE_MODEL_DESC,
BooleanProperty.TYPE)); BooleanProperty.TYPE));
cliOptions.add(new CliOption(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING, CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING_DESC,
BooleanProperty.TYPE));
cliOptions.add(new CliOption(FULL_JAVA_UTIL, "whether to use fully qualified name for classes under java.util", cliOptions.add(new CliOption(FULL_JAVA_UTIL, "whether to use fully qualified name for classes under java.util",
BooleanProperty.TYPE).defaultValue(Boolean.FALSE.toString())); BooleanProperty.TYPE).defaultValue(Boolean.FALSE.toString()));
@ -181,6 +160,10 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
this.setLibrary((String) additionalProperties.get(CodegenConstants.LIBRARY)); this.setLibrary((String) additionalProperties.get(CodegenConstants.LIBRARY));
} }
if(additionalProperties.containsKey(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING)) {
this.setSerializeBigDecimalAsString(Boolean.valueOf(additionalProperties.get(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING).toString()));
}
// need to put back serializableModel (boolean) into additionalProperties as value in additionalProperties is string // need to put back serializableModel (boolean) into additionalProperties as value in additionalProperties is string
additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, serializableModel); additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, serializableModel);
@ -212,6 +195,11 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
this.sanitizeConfig(); this.sanitizeConfig();
// optional jackson mappings for BigDecimal support
importMapping.put("ToStringSerializer", "com.fasterxml.jackson.databind.ser.std.ToStringSerializer");
importMapping.put("JsonSerialize", "com.fasterxml.jackson.databind.annotation.JsonSerialize");
final String invokerFolder = (sourceFolder + '/' + invokerPackage).replace(".", "/"); final String invokerFolder = (sourceFolder + '/' + invokerPackage).replace(".", "/");
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
@ -471,6 +459,26 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
return codegenModel; return codegenModel;
} }
@Override
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
if(serializeBigDecimalAsString) {
if (property.baseType.equals("BigDecimal")) {
// we serialize BigDecimal as `string` to avoid precision loss
property.vendorExtensions.put("extraAnnotation", "@JsonSerialize(using = ToStringSerializer.class)");
// this requires some more imports to be added for this model...
model.imports.add("ToStringSerializer");
model.imports.add("JsonSerialize");
}
}
return;
}
@Override
public void postProcessParameter(CodegenParameter parameter) {
return;
}
@Override @Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) { public Map<String, Object> postProcessModels(Map<String, Object> objs) {
List<Object> models = (List<Object>) objs.get("models"); List<Object> models = (List<Object>) objs.get("models");
@ -702,6 +710,9 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
this.localVariablePrefix = localVariablePrefix; this.localVariablePrefix = localVariablePrefix;
} }
public void setSerializeBigDecimalAsString(boolean s) {
this.serializeBigDecimalAsString = s;
}
public Boolean getSerializableModel() { public Boolean getSerializableModel() {
return serializableModel; return serializableModel;

View File

@ -14,6 +14,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} {{#seriali
* minimum: {{minimum}}{{/minimum}}{{#maximum}} * minimum: {{minimum}}{{/minimum}}{{#maximum}}
* maximum: {{maximum}}{{/maximum}} * maximum: {{maximum}}{{/maximum}}
**/ **/
{{#vendorExtensions.extraAnnotation}}{{vendorExtensions.extraAnnotation}}{{/vendorExtensions.extraAnnotation}}
@ApiModelProperty({{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") @ApiModelProperty({{#required}}required = {{required}}, {{/required}}value = "{{{description}}}")
@JsonProperty("{{baseName}}") @JsonProperty("{{baseName}}")
public {{{datatypeWithEnum}}} {{getter}}() { public {{{datatypeWithEnum}}} {{getter}}() {

View File

@ -4,8 +4,6 @@ import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.java.JavaClientOptionsTest; import io.swagger.codegen.java.JavaClientOptionsTest;
import io.swagger.codegen.languages.JavaInflectorServerCodegen; import io.swagger.codegen.languages.JavaInflectorServerCodegen;
import io.swagger.codegen.options.JavaInflectorServerOptionsProvider; import io.swagger.codegen.options.JavaInflectorServerOptionsProvider;
import io.swagger.codegen.options.JavaOptionsProvider;
import mockit.Expectations; import mockit.Expectations;
import mockit.Tested; import mockit.Tested;
@ -50,6 +48,8 @@ public class JavaInflectorServerOptionsTest extends JavaClientOptionsTest {
times = 1; times = 1;
clientCodegen.setFullJavaUtil(Boolean.valueOf(JavaInflectorServerOptionsProvider.FULL_JAVA_UTIL_VALUE)); clientCodegen.setFullJavaUtil(Boolean.valueOf(JavaInflectorServerOptionsProvider.FULL_JAVA_UTIL_VALUE));
times = 1; times = 1;
clientCodegen.setSerializeBigDecimalAsString(true);
times = 1;
}}; }};
} }
} }

View File

@ -38,6 +38,7 @@ public class JavaOptionsProvider implements OptionsProvider {
.put(CodegenConstants.SERIALIZABLE_MODEL, SERIALIZABLE_MODEL_VALUE) .put(CodegenConstants.SERIALIZABLE_MODEL, SERIALIZABLE_MODEL_VALUE)
.put(JavaClientCodegen.FULL_JAVA_UTIL, FULL_JAVA_UTIL_VALUE) .put(JavaClientCodegen.FULL_JAVA_UTIL, FULL_JAVA_UTIL_VALUE)
.put(CodegenConstants.LIBRARY, LIBRARY_VALUE) .put(CodegenConstants.LIBRARY, LIBRARY_VALUE)
.put(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING, "true")
.build(); .build();
} }