forked from loafle/openapi-generator-original
Scala Cask oneOf support (#20051)
* added support for 'oneOf' types represented as unions also updated libs and an 'errors' field rename to address name clashes with likely/popular field names * Created cask-specific petstore example which Includes a oneOf and allOf example
This commit is contained in:
parent
bfcfc6ff25
commit
6792218775
@ -1,6 +1,6 @@
|
||||
generatorName: scala-cask
|
||||
outputDir: samples/server/petstore/scala-cask
|
||||
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
|
||||
inputSpec: modules/openapi-generator/src/test/resources/3_0/scala-cask/petstore.yaml
|
||||
templateDir: modules/openapi-generator/src/main/resources/scala-cask
|
||||
additionalProperties:
|
||||
hideGenerationTimestamp: "true"
|
||||
|
@ -18,6 +18,7 @@ package org.openapitools.codegen.languages;
|
||||
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.media.Schema;
|
||||
import io.swagger.v3.oas.models.parameters.RequestBody;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.openapitools.codegen.*;
|
||||
import org.openapitools.codegen.model.ModelMap;
|
||||
@ -394,6 +395,12 @@ public class ScalaCaskServerCodegen extends AbstractScalaCodegen implements Code
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This class is used in pathExtractorParams.mustache.
|
||||
*
|
||||
* It exposes some methods which make it more readable
|
||||
* for that mustache snippet, and also isolates the logic needed for the path extractors
|
||||
*/
|
||||
public static class ParamPart {
|
||||
final CodegenParameter param;
|
||||
final String name;
|
||||
@ -416,7 +423,9 @@ public class ScalaCaskServerCodegen extends AbstractScalaCodegen implements Code
|
||||
}
|
||||
|
||||
/**
|
||||
* Cask will compile but 'initialize' can throw a route overlap exception:
|
||||
* This data structure is here to manually identify and fix routes which will overlap (e.g. GET /foo/bar and GET /foo/bazz)
|
||||
*
|
||||
* If we added these as individual routes, then Cask itself will compile, but calling 'initialize' throws a route overlap exception:
|
||||
* <p>
|
||||
* {{{
|
||||
* Routes overlap with wildcards: get /user/logout, get /user/:username, get /user/login
|
||||
@ -672,9 +681,12 @@ public class ScalaCaskServerCodegen extends AbstractScalaCodegen implements Code
|
||||
|
||||
model.getVars().forEach(this::postProcessProperty);
|
||||
model.getAllVars().forEach(this::postProcessProperty);
|
||||
|
||||
|
||||
model.vendorExtensions.put("x-has-one-of", model.oneOf != null && !model.oneOf.isEmpty());
|
||||
}
|
||||
|
||||
private static void postProcessOperation(CodegenOperation op) {
|
||||
private static void postProcessOperation(final CodegenOperation op) {
|
||||
// force http method to lower case
|
||||
op.httpMethod = op.httpMethod.toLowerCase(Locale.ROOT);
|
||||
|
||||
@ -710,9 +722,33 @@ public class ScalaCaskServerCodegen extends AbstractScalaCodegen implements Code
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
|
||||
var responseType = responses.isEmpty() ? "Unit" : String.join(" | ", responses);
|
||||
op.vendorExtensions.put("x-import-response-implicits", importResponseImplicits(op));
|
||||
op.vendorExtensions.put("x-response-type", responseType);
|
||||
}
|
||||
|
||||
/**
|
||||
* We need to bring the response type into scope in order to use the upickle implicits
|
||||
* only if the response type has a 'oneOf' type, which means it's a union type with a
|
||||
* companion object containing the ReadWriter
|
||||
*
|
||||
* @param op
|
||||
* @return true if we need to provide an import
|
||||
*/
|
||||
private static boolean importResponseImplicits(final CodegenOperation op) {
|
||||
final Set<String> importBlacklist = Set.of("File");
|
||||
|
||||
boolean doImport = false;
|
||||
for (var response : op.responses) {
|
||||
// we should ignore generic types like Seq[...] or Map[..] types
|
||||
var isPolymorphic = response.dataType != null && response.dataType.contains("[");
|
||||
if (response.isModel && !importBlacklist.contains(response.dataType) && !isPolymorphic) {
|
||||
doImport = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return doImport;
|
||||
}
|
||||
|
||||
/**
|
||||
* primitive or enum types don't have Data representations
|
||||
* @param p the property
|
||||
@ -747,6 +783,10 @@ public class ScalaCaskServerCodegen extends AbstractScalaCodegen implements Code
|
||||
return "byte".equalsIgnoreCase(p.dataFormat); // &&
|
||||
}
|
||||
|
||||
private static boolean wrapInOptional(CodegenProperty p) {
|
||||
return !p.required && !p.isArray && !p.isMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* this parameter is used to create the function:
|
||||
* {{{
|
||||
@ -761,19 +801,18 @@ public class ScalaCaskServerCodegen extends AbstractScalaCodegen implements Code
|
||||
* and then back again
|
||||
*/
|
||||
private static String asDataCode(final CodegenProperty p, final Set<String> typesWhichDoNotNeedMapping) {
|
||||
final var wrapInOptional = !p.required && !p.isArray && !p.isMap;
|
||||
String code = "";
|
||||
|
||||
String dv = defaultValueNonOption(p, p.defaultValue);
|
||||
|
||||
if (doesNotNeedMapping(p, typesWhichDoNotNeedMapping)) {
|
||||
if (wrapInOptional) {
|
||||
if (wrapInOptional(p)) {
|
||||
code = String.format(Locale.ROOT, "%s.getOrElse(%s) /* 1 */", p.name, dv);
|
||||
} else {
|
||||
code = String.format(Locale.ROOT, "%s /* 2 */", p.name);
|
||||
}
|
||||
} else {
|
||||
if (wrapInOptional) {
|
||||
if (wrapInOptional(p)) {
|
||||
if (isByteArray(p)) {
|
||||
code = String.format(Locale.ROOT, "%s.getOrElse(%s) /* 3 */", p.name, dv);
|
||||
} else {
|
||||
@ -782,11 +821,15 @@ public class ScalaCaskServerCodegen extends AbstractScalaCodegen implements Code
|
||||
} else if (p.isArray) {
|
||||
if (isByteArray(p)) {
|
||||
code = String.format(Locale.ROOT, "%s /* 5 */", p.name);
|
||||
} else if (!isObjectArray(p)) {
|
||||
code = String.format(Locale.ROOT, "%s /* 5.1 */", p.name);
|
||||
} else {
|
||||
code = String.format(Locale.ROOT, "%s.map(_.asData) /* 6 */", p.name);
|
||||
}
|
||||
} else if (p.isMap) {
|
||||
code = String.format(Locale.ROOT, "%s /* 7 */", p.name);
|
||||
} else {
|
||||
code = String.format(Locale.ROOT, "%s.asData /* 7 */", p.name);
|
||||
code = String.format(Locale.ROOT, "%s.asData /* 8 */", p.name);
|
||||
}
|
||||
}
|
||||
return code;
|
||||
@ -807,17 +850,16 @@ public class ScalaCaskServerCodegen extends AbstractScalaCodegen implements Code
|
||||
* @return
|
||||
*/
|
||||
private static String asModelCode(final CodegenProperty p, final Set<String> typesWhichDoNotNeedMapping) {
|
||||
final var wrapInOptional = !p.required && !p.isArray && !p.isMap;
|
||||
String code = "";
|
||||
|
||||
if (doesNotNeedMapping(p, typesWhichDoNotNeedMapping)) {
|
||||
if (wrapInOptional) {
|
||||
if (wrapInOptional(p)) {
|
||||
code = String.format(Locale.ROOT, "Option(%s) /* 1 */", p.name);
|
||||
} else {
|
||||
code = String.format(Locale.ROOT, "%s /* 2 */", p.name);
|
||||
}
|
||||
} else {
|
||||
if (wrapInOptional) {
|
||||
if (wrapInOptional(p)) {
|
||||
if (isByteArray(p)) {
|
||||
code = String.format(Locale.ROOT, "Option(%s) /* 3 */", p.name);
|
||||
} else {
|
||||
@ -825,6 +867,8 @@ public class ScalaCaskServerCodegen extends AbstractScalaCodegen implements Code
|
||||
}
|
||||
} else if (p.isArray) {
|
||||
code = String.format(Locale.ROOT, "%s.map(_.asModel) /* 5 */", p.name);
|
||||
} else if (p.isMap) {
|
||||
code = String.format(Locale.ROOT, "%s /* 5.1 */", p.name);
|
||||
} else {
|
||||
code = String.format(Locale.ROOT, "%s.asModel /* 6 */", p.name);
|
||||
}
|
||||
@ -863,8 +907,17 @@ public class ScalaCaskServerCodegen extends AbstractScalaCodegen implements Code
|
||||
return text;
|
||||
}
|
||||
|
||||
private static boolean hasItemModel(final CodegenProperty p) {
|
||||
return p.items != null && p.items.isModel;
|
||||
}
|
||||
|
||||
private static boolean isObjectArray(final CodegenProperty p) {
|
||||
return p.isArray && hasItemModel(p);
|
||||
}
|
||||
|
||||
private void postProcessProperty(final CodegenProperty p) {
|
||||
p.vendorExtensions.put("x-datatype-model", asScalaDataType(p, p.required, false));
|
||||
|
||||
p.vendorExtensions.put("x-datatype-model", asScalaDataType(p, p.required, false, wrapInOptional(p)));
|
||||
p.vendorExtensions.put("x-defaultValue-model", defaultValue(p, p.required, p.defaultValue));
|
||||
final String dataTypeData = asScalaDataType(p, p.required, true);
|
||||
p.vendorExtensions.put("x-datatype-data", dataTypeData);
|
||||
@ -878,7 +931,7 @@ public class ScalaCaskServerCodegen extends AbstractScalaCodegen implements Code
|
||||
p._enum = p._enum.stream().map(this::ensureNonKeyword).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* This is a fix for the enum property "type" declared like this:
|
||||
* {{{
|
||||
* type:
|
||||
@ -908,6 +961,9 @@ public class ScalaCaskServerCodegen extends AbstractScalaCodegen implements Code
|
||||
)).collect(Collectors.toSet());
|
||||
typesWhichShouldNotBeMapped.add("byte");
|
||||
|
||||
// when deserialising map objects, the logic is tricky.
|
||||
p.vendorExtensions.put("x-deserialize-asModelMap", p.isMap && hasItemModel(p));
|
||||
|
||||
// the 'asModel' logic for modelData.mustache
|
||||
//
|
||||
// if it's optional (not required), then wrap the value in Option()
|
||||
@ -916,16 +972,6 @@ public class ScalaCaskServerCodegen extends AbstractScalaCodegen implements Code
|
||||
p.vendorExtensions.put("x-asData", asDataCode(p, typesWhichShouldNotBeMapped));
|
||||
p.vendorExtensions.put("x-asModel", asModelCode(p, typesWhichShouldNotBeMapped));
|
||||
|
||||
// if it's an array or optional, we need to map it as a model -- unless it's a map,
|
||||
// in which case we have to map the values
|
||||
boolean hasItemModel = p.items != null && p.items.isModel;
|
||||
boolean isObjectArray = p.isArray && hasItemModel;
|
||||
boolean isOptionalObj = !p.required && p.isModel;
|
||||
p.vendorExtensions.put("x-map-asModel", (isOptionalObj || isObjectArray) && !p.isMap);
|
||||
|
||||
// when deserialising map objects, the logic is tricky.
|
||||
p.vendorExtensions.put("x-deserialize-asModelMap", p.isMap && hasItemModel);
|
||||
|
||||
// for some reason, an openapi spec with pattern field like this:
|
||||
// pattern: '^[A-Za-z]+$'
|
||||
// will result in the pattern property text of
|
||||
@ -934,6 +980,20 @@ public class ScalaCaskServerCodegen extends AbstractScalaCodegen implements Code
|
||||
p.pattern = p.pattern.substring(1, p.pattern.length() - 1);
|
||||
}
|
||||
|
||||
// in our model class definition laid out in modelClass.mustache, we use 'Option' for non-required
|
||||
// properties only when they don't have a sensible 'empty' value (e.g. maps and lists).
|
||||
//
|
||||
// that is to say, we're trying to avoid having:
|
||||
//
|
||||
// someOptionalField : Option[Seq[Foo]]
|
||||
//
|
||||
// when we could just have e.g.
|
||||
//
|
||||
// someOptionalField : Seq[Foo]
|
||||
//
|
||||
// with an empty value
|
||||
p.vendorExtensions.put("x-model-needs-option", wrapInOptional(p));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -45,6 +45,10 @@ class {{classname}}Routes(service : {{classname}}Service[Try]) extends cask.Rout
|
||||
|
||||
val result = {{>parseHttpParams}}
|
||||
|
||||
{{#vendorExtensions.x-import-response-implicits}}
|
||||
import {{vendorExtensions.x-response-type}}.{given, *} // this brings in upickle in the case of union (oneOf) types
|
||||
{{/vendorExtensions.x-import-response-implicits}}
|
||||
|
||||
(result : @unchecked) match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
{{#responses}}
|
||||
|
@ -13,12 +13,24 @@ import upickle.default.*
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
|
||||
{{#isEnum}}
|
||||
{{>modelEnum}}
|
||||
{{/isEnum}}
|
||||
{{^isEnum}}
|
||||
{{>modelClass}}
|
||||
{{/isEnum}}
|
||||
{{#vendorExtensions.x-has-one-of}}
|
||||
|
||||
type {{classname}} = {{#oneOf}}{{{.}}}{{^-last}} | {{/-last}}{{/oneOf}}
|
||||
object {{{classname}}} {
|
||||
|
||||
given RW[{{{classname}}}] = RW.merge({{#oneOf}}summon[RW[{{{.}}}]]{{^-last}}, {{/-last}}{{/oneOf}})
|
||||
}
|
||||
|
||||
{{/vendorExtensions.x-has-one-of}}
|
||||
{{^vendorExtensions.x-has-one-of}}
|
||||
{{#isEnum}}
|
||||
{{>modelEnum}}
|
||||
{{/isEnum}}
|
||||
{{^isEnum}}
|
||||
{{>modelClass}}
|
||||
{{/isEnum}}
|
||||
{{/vendorExtensions.x-has-one-of}}
|
||||
|
||||
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
|
@ -4,7 +4,7 @@ case class {{classname}}(
|
||||
{{#description}}
|
||||
/* {{{description}}} */
|
||||
{{/description}}
|
||||
{{name}}: {{#isEnum}}{{^required}}Option[{{/required}}{{classname}}.{{datatypeWithEnum}}{{^required}}]{{/required}}{{/isEnum}}{{^isEnum}}{{{vendorExtensions.x-datatype-model}}}{{/isEnum}}{{^required}} = {{{vendorExtensions.x-defaultValue-model}}} {{/required}}{{^-last}},{{/-last}}
|
||||
{{name}}: {{#isEnum}}{{#vendorExtensions.x-model-needs-option}}Option[{{/vendorExtensions.x-model-needs-option}}{{classname}}.{{datatypeWithEnum}}{{#vendorExtensions.x-model-needs-option}}]{{/vendorExtensions.x-model-needs-option}}{{/isEnum}}{{^isEnum}}{{{vendorExtensions.x-datatype-model}}}{{/isEnum}}{{^required}} = {{{vendorExtensions.x-defaultValue-model}}} {{/required}}{{^-last}},{{/-last}}
|
||||
{{/vars}}
|
||||
|
||||
{{#isAdditionalPropertiesTrue}}, additionalProperties : ujson.Value = ujson.Null{{/isAdditionalPropertiesTrue}}
|
||||
|
@ -13,11 +13,40 @@ import upickle.default.*
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
|
||||
{{#vendorExtensions.x-has-one-of}}
|
||||
type {{{classname}}}Data = {{#oneOf}}{{{.}}}Data{{^-last}} | {{/-last}}{{/oneOf}}
|
||||
|
||||
object {{{classname}}}Data {
|
||||
|
||||
def validated(d8a : {{{classname}}}Data, failFast: Boolean) : Try[{{{classname}}}] = {
|
||||
d8a match {
|
||||
{{#oneOf}}
|
||||
case value : {{{.}}}Data => value.validated(failFast)
|
||||
{{/oneOf}}
|
||||
}
|
||||
}
|
||||
|
||||
def fromJsonString(jason : String) = fromJson {
|
||||
try {
|
||||
read[ujson.Value](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason': $e")
|
||||
}
|
||||
}
|
||||
|
||||
def fromJson(jason : ujson.Value) : {{{classname}}}Data = {
|
||||
val attempt = {{#oneOf}}{{^-first}}.orElse({{/-first}} Try({{{.}}}Data.fromJson(jason)) {{^-first}}) /* not first */{{/-first}} {{/oneOf}}
|
||||
attempt.get
|
||||
}
|
||||
}
|
||||
{{/vendorExtensions.x-has-one-of}}
|
||||
{{^vendorExtensions.x-has-one-of}}
|
||||
{{#isEnum}}
|
||||
{{>modelDataEnum}}
|
||||
{{/isEnum}}
|
||||
{{^isEnum}}
|
||||
{{>modelDataClass}}
|
||||
{{/isEnum}}
|
||||
{{/vendorExtensions.x-has-one-of}}
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
|
@ -26,73 +26,73 @@ case class {{classname}}Data(
|
||||
}
|
||||
|
||||
def validationErrors(path : Seq[Field], failFast : Boolean) : Seq[ValidationError] = {
|
||||
val errors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
val _allValidationErrors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
{{#vars}}
|
||||
// ================== {{name}} validation ==================
|
||||
{{#pattern}}
|
||||
// validate against pattern '{{{pattern}}}'
|
||||
if (errors.isEmpty || !failFast) {
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
val regex = """{{{pattern}}}"""
|
||||
if {{name}} == null || !regex.r.matches({{name}}) then
|
||||
errors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"value '${{name}}' doesn't match pattern $regex")
|
||||
_allValidationErrors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"value '${{name}}' doesn't match pattern $regex")
|
||||
}
|
||||
{{/pattern}}
|
||||
{{#minimum}}
|
||||
// validate against {{#exclusiveMinimum}}exclusive {{/exclusiveMinimum}}minimum {{minimum}}
|
||||
if (errors.isEmpty || !failFast) {
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
if !({{name}} >{{^exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}) then
|
||||
errors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"value '${{name}}' is not greater than the {{#exclusiveMinimum}}exclusive {{/exclusiveMinimum}}minimum value {{minimum}}")
|
||||
_allValidationErrors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"value '${{name}}' is not greater than the {{#exclusiveMinimum}}exclusive {{/exclusiveMinimum}}minimum value {{minimum}}")
|
||||
}
|
||||
{{/minimum}}
|
||||
{{#maximum}}
|
||||
// validate against {{#exclusiveMaximum}}exclusive {{/exclusiveMaximum}}maximum {{maximum}}
|
||||
if (errors.isEmpty || !failFast) {
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
if !({{name}} <{{^exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}) then
|
||||
errors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"value '${{name}}' is not greater than the {{#exclusiveMaximum}}exclusive {{/exclusiveMaximum}}maximum value {{maximum}}")
|
||||
_allValidationErrors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"value '${{name}}' is not greater than the {{#exclusiveMaximum}}exclusive {{/exclusiveMaximum}}maximum value {{maximum}}")
|
||||
}
|
||||
{{/maximum}}
|
||||
{{#minLength}}
|
||||
// validate min length {{minLength}}
|
||||
if (errors.isEmpty || !failFast) {
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
val len = if {{name}} == null then 0 else {{name}}.length
|
||||
if (len < {{minLength}}) {
|
||||
errors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"length $len is shorter than the min length {{minLength}}")
|
||||
_allValidationErrors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"length $len is shorter than the min length {{minLength}}")
|
||||
}
|
||||
}
|
||||
{{/minLength}}
|
||||
{{#maxLength}}
|
||||
// validate max length {{maxLength}}
|
||||
if (errors.isEmpty || !failFast) {
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
val len = if {{name}} == null then 0 else {{name}}.length
|
||||
if (len < {{maxLength}}) {
|
||||
errors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"length $len is longer than the max length {{maxLength}}")
|
||||
_allValidationErrors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"length $len is longer than the max length {{maxLength}}")
|
||||
}
|
||||
}
|
||||
{{/maxLength}}
|
||||
{{#isEmail}}
|
||||
// validate {{name}} is a valid email address
|
||||
if (errors.isEmpty || !failFast) {
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
val emailRegex = """^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"""
|
||||
// validate {{name}} is email
|
||||
if ({{name}} == null || !emailRegex.r.matches({{name}})) {
|
||||
errors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"${{name}} is not a valid email address according to the pattern $emailRegex")
|
||||
_allValidationErrors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"${{name}} is not a valid email address according to the pattern $emailRegex")
|
||||
}
|
||||
}
|
||||
{{/isEmail}}
|
||||
{{#required}}{{^isPrimitiveType}}
|
||||
if (errors.isEmpty || !failFast) {
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
if ({{name}} == null) {
|
||||
errors += ValidationError(path :+ {{classname}}.Fields.{{name}}, "{{name}} is a required field and cannot be null")
|
||||
_allValidationErrors += ValidationError(path :+ {{classname}}.Fields.{{name}}, "{{name}} is a required field and cannot be null")
|
||||
}
|
||||
}
|
||||
{{/isPrimitiveType}}{{/required}}
|
||||
{{#uniqueItems}}
|
||||
// validate {{name}} has unique items
|
||||
if (errors.isEmpty || !failFast) {
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
if ({{name}} != null) {
|
||||
{{name}}.foldLeft(Set[{{{vendorExtensions.x-containertype-data}}}]()) {
|
||||
case (set, next) if set.contains(next) =>
|
||||
errors += ValidationError(
|
||||
_allValidationErrors += ValidationError(
|
||||
path :+ {{classname}}.Fields.{{name}},
|
||||
s"duplicate value: $next"
|
||||
)
|
||||
@ -103,10 +103,10 @@ case class {{classname}}Data(
|
||||
}
|
||||
{{/uniqueItems}}
|
||||
{{#multipleOf}}
|
||||
if (errors.isEmpty || !failFast) {
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
// validate {{name}} multiple of {{multipleOf}}
|
||||
if ({{name}} % {{multipleOf}} != 0) {
|
||||
errors += ValidationError(
|
||||
_allValidationErrors += ValidationError(
|
||||
path :+ {{classname}}.Fields.{{name}},
|
||||
s"${{name}} is not a multiple of {{multipleOf}}"
|
||||
)
|
||||
@ -115,30 +115,30 @@ case class {{classname}}Data(
|
||||
{{/multipleOf}}
|
||||
{{#minItems}}
|
||||
// validate min items {{minItems}}
|
||||
if (errors.isEmpty || !failFast) {
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
val len = if {{name}} == null then 0 else {{name}}.size
|
||||
if (len < {{minItems}}) {
|
||||
errors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"{{name}} has $len, which is less than the min items {{minItems}}")
|
||||
_allValidationErrors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"{{name}} has $len, which is less than the min items {{minItems}}")
|
||||
}
|
||||
}
|
||||
{{/minItems}}
|
||||
{{#maxItems}}
|
||||
// validate min items {{maxItems}}
|
||||
if (errors.isEmpty || !failFast) {
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
val len = if {{name}} == null then 0 else {{name}}.size
|
||||
if (len > {{maxItems}}) {
|
||||
errors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"{{name}} has $len, which is greater than the max items {{maxItems}}")
|
||||
_allValidationErrors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"{{name}} has $len, which is greater than the max items {{maxItems}}")
|
||||
}
|
||||
}
|
||||
{{/maxItems}}
|
||||
{{#minProperties}} TODO - minProperties {{/minProperties}}
|
||||
{{#maxProperties}} TODO - maxProperties {{/maxProperties}}
|
||||
{{#items}}{{#isModel}}
|
||||
if (errors.isEmpty || !failFast) {
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
if ({{name}} != null) {
|
||||
{{name}}.zipWithIndex.foreach {
|
||||
case (value, i) if errors.isEmpty || !failFast =>
|
||||
errors ++= value.validationErrors(
|
||||
case (value, i) if _allValidationErrors.isEmpty || !failFast =>
|
||||
_allValidationErrors ++= value.validationErrors(
|
||||
path :+ {{classname}}.Fields.{{name}} :+ Field(i.toString),
|
||||
failFast)
|
||||
case (value, i) =>
|
||||
@ -148,13 +148,13 @@ case class {{classname}}Data(
|
||||
{{/isModel}}{{/items}}
|
||||
{{#isModel}}
|
||||
// validating {{name}}
|
||||
if (errors.isEmpty || !failFast) {
|
||||
if {{name}} != null then errors ++= {{name}}.validationErrors(path :+ {{classname}}.Fields.{{name}}, failFast)
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
if {{name}} != null then _allValidationErrors ++= {{name}}.validationErrors(path :+ {{classname}}.Fields.{{name}}, failFast)
|
||||
}
|
||||
{{/isModel}}
|
||||
|
||||
{{/vars}}
|
||||
errors.toSeq
|
||||
_allValidationErrors.toSeq
|
||||
}
|
||||
|
||||
/**
|
||||
@ -180,6 +180,8 @@ case class {{classname}}Data(
|
||||
|
||||
object {{classname}}Data {
|
||||
|
||||
def validated(d8a : {{classname}}Data, failFast : Boolean) : scala.util.Try[{{classname}}] = d8a.validated(failFast)
|
||||
|
||||
def fromJson(jason : ujson.Value) : {{classname}}Data = try {
|
||||
val data = read[{{classname}}Data](jason)
|
||||
{{^isAdditionalPropertiesTrue}}
|
||||
|
@ -28,7 +28,8 @@ class {{classname}}Test extends AnyWordSpec with Matchers {
|
||||
err.getMessage should startWith ("Error parsing json 'invalid jason'")
|
||||
}
|
||||
"""parse {{example}}""" ignore {
|
||||
val Failure(err : ValidationErrors) = {{classname}}Data.fromJsonString("""{{example}}""").validated()
|
||||
val d8a = {{classname}}Data.fromJsonString("""{{example}}""")
|
||||
val Failure(err : ValidationErrors) = {{classname}}Data.validated(d8a, true)
|
||||
|
||||
sys.error("TODO")
|
||||
}
|
||||
|
@ -40,7 +40,10 @@
|
||||
{{^isMap}}
|
||||
{{paramName}}Json <- Parsed.fromTry(request.bodyAsJson)
|
||||
{{paramName}}Data <- Parsed.eval({{vendorExtensions.x-container-type}}Data.fromJson({{paramName}}Json)) /* not array or map */
|
||||
{{paramName}} <- Parsed.fromTry({{paramName}}Data.validated(failFast))
|
||||
{{paramName}}{{^required}}Opt{{/required}} <- Parsed.fromTry({{vendorExtensions.x-container-type}}Data.validated({{paramName}}Data, failFast))
|
||||
{{^required}}
|
||||
{{paramName}} = Option({{paramName}}Opt)
|
||||
{{/required}}
|
||||
{{/isMap}}
|
||||
{{/isArray}}
|
||||
{{/vendorExtensions.x-consumes-json}}
|
||||
|
@ -1 +1 @@
|
||||
sbt.version=1.9.9
|
||||
sbt.version=1.10.3
|
||||
|
@ -1,4 +1,4 @@
|
||||
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6")
|
||||
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "1.2.0")
|
||||
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.16.0")
|
||||
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.17.0")
|
||||
addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.2.0")
|
@ -0,0 +1,905 @@
|
||||
openapi: 3.0.0
|
||||
servers:
|
||||
- url: 'http://petstore.swagger.io/v2'
|
||||
info:
|
||||
description: >-
|
||||
This is a sample server Petstore server. For this sample, you can use the api key
|
||||
`special-key` to test the authorization filters.
|
||||
version: 1.0.0
|
||||
title: OpenAPI Petstore
|
||||
license:
|
||||
name: Apache-2.0
|
||||
url: 'https://www.apache.org/licenses/LICENSE-2.0.html'
|
||||
tags:
|
||||
- name: pet
|
||||
description: Everything about your Pets
|
||||
- name: store
|
||||
description: Access to Petstore orders
|
||||
- name: user
|
||||
description: Operations about user
|
||||
paths:
|
||||
/complex-types:
|
||||
post:
|
||||
tags:
|
||||
- complexRoute
|
||||
operationId: oneOfRequestAndResponse
|
||||
summary: Example route with 'oneOf' content and response
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/ComplexRequest'
|
||||
- $ref: '#/components/schemas/AllOfRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Success
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/SomeResponse1'
|
||||
- $ref: '#/components/schemas/SomeResponse2'
|
||||
/pet:
|
||||
post:
|
||||
tags:
|
||||
- pet
|
||||
summary: Add a new pet to the store
|
||||
description: ''
|
||||
operationId: addPet
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
content:
|
||||
application/xml:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Pet'
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Pet'
|
||||
'405':
|
||||
description: Invalid input
|
||||
security:
|
||||
- petstore_auth:
|
||||
- 'write:pets'
|
||||
- 'read:pets'
|
||||
requestBody:
|
||||
$ref: '#/components/requestBodies/Pet'
|
||||
put:
|
||||
tags:
|
||||
- pet
|
||||
summary: Update an existing pet
|
||||
description: ''
|
||||
operationId: updatePet
|
||||
externalDocs:
|
||||
url: "http://petstore.swagger.io/v2/doc/updatePet"
|
||||
description: "API documentation for the updatePet operation"
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
content:
|
||||
application/xml:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Pet'
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Pet'
|
||||
'400':
|
||||
description: Invalid ID supplied
|
||||
'404':
|
||||
description: Pet not found
|
||||
'405':
|
||||
description: Validation exception
|
||||
security:
|
||||
- petstore_auth:
|
||||
- 'write:pets'
|
||||
- 'read:pets'
|
||||
requestBody:
|
||||
$ref: '#/components/requestBodies/Pet'
|
||||
/pet/findByStatus:
|
||||
get:
|
||||
tags:
|
||||
- pet
|
||||
summary: Finds Pets by status
|
||||
description: Multiple status values can be provided with comma separated strings
|
||||
operationId: findPetsByStatus
|
||||
parameters:
|
||||
- name: status
|
||||
in: query
|
||||
description: Status values that need to be considered for filter
|
||||
required: true
|
||||
style: form
|
||||
explode: false
|
||||
deprecated: true
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
enum:
|
||||
- available
|
||||
- pending
|
||||
- sold
|
||||
default: available
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
content:
|
||||
application/xml:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Pet'
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Pet'
|
||||
'400':
|
||||
description: Invalid status value
|
||||
security:
|
||||
- petstore_auth:
|
||||
- 'read:pets'
|
||||
/pet/findByTags:
|
||||
get:
|
||||
tags:
|
||||
- pet
|
||||
summary: Finds Pets by tags
|
||||
description: >-
|
||||
Multiple tags can be provided with comma separated strings. Use tag1,
|
||||
tag2, tag3 for testing.
|
||||
operationId: findPetsByTags
|
||||
parameters:
|
||||
- name: tags
|
||||
in: query
|
||||
description: Tags to filter by
|
||||
required: true
|
||||
style: form
|
||||
explode: false
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
content:
|
||||
application/xml:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Pet'
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Pet'
|
||||
'400':
|
||||
description: Invalid tag value
|
||||
security:
|
||||
- petstore_auth:
|
||||
- 'read:pets'
|
||||
deprecated: true
|
||||
'/pet/{petId}':
|
||||
get:
|
||||
tags:
|
||||
- pet
|
||||
summary: Find pet by ID
|
||||
description: Returns a single pet
|
||||
operationId: getPetById
|
||||
parameters:
|
||||
- name: petId
|
||||
in: path
|
||||
description: ID of pet to return
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
content:
|
||||
application/xml:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Pet'
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Pet'
|
||||
'400':
|
||||
description: Invalid ID supplied
|
||||
'404':
|
||||
description: Pet not found
|
||||
security:
|
||||
- api_key: []
|
||||
post:
|
||||
tags:
|
||||
- pet
|
||||
summary: Updates a pet in the store with form data
|
||||
description: ''
|
||||
operationId: updatePetWithForm
|
||||
parameters:
|
||||
- name: petId
|
||||
in: path
|
||||
description: ID of pet that needs to be updated
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
responses:
|
||||
'405':
|
||||
description: Invalid input
|
||||
security:
|
||||
- petstore_auth:
|
||||
- 'write:pets'
|
||||
- 'read:pets'
|
||||
requestBody:
|
||||
content:
|
||||
application/x-www-form-urlencoded:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
description: Updated name of the pet
|
||||
type: string
|
||||
status:
|
||||
description: Updated status of the pet
|
||||
type: string
|
||||
delete:
|
||||
tags:
|
||||
- pet
|
||||
summary: Deletes a pet
|
||||
description: ''
|
||||
operationId: deletePet
|
||||
parameters:
|
||||
- name: api_key
|
||||
in: header
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
- name: petId
|
||||
in: path
|
||||
description: Pet id to delete
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
responses:
|
||||
'400':
|
||||
description: Invalid pet value
|
||||
security:
|
||||
- petstore_auth:
|
||||
- 'write:pets'
|
||||
- 'read:pets'
|
||||
'/pet/{petId}/uploadImage':
|
||||
post:
|
||||
tags:
|
||||
- pet
|
||||
summary: uploads an image
|
||||
description: ''
|
||||
operationId: uploadFile
|
||||
parameters:
|
||||
- name: petId
|
||||
in: path
|
||||
description: ID of pet to update
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ApiResponse'
|
||||
security:
|
||||
- petstore_auth:
|
||||
- 'write:pets'
|
||||
- 'read:pets'
|
||||
requestBody:
|
||||
content:
|
||||
multipart/form-data:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
additionalMetadata:
|
||||
description: Additional data to pass to server
|
||||
type: string
|
||||
file:
|
||||
description: file to upload
|
||||
type: string
|
||||
format: binary
|
||||
/store/inventory:
|
||||
get:
|
||||
tags:
|
||||
- store
|
||||
summary: Returns pet inventories by status
|
||||
description: Returns a map of status codes to quantities
|
||||
operationId: getInventory
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: integer
|
||||
format: int32
|
||||
security:
|
||||
- api_key: []
|
||||
/store/order:
|
||||
post:
|
||||
tags:
|
||||
- store
|
||||
summary: Place an order for a pet
|
||||
description: ''
|
||||
operationId: placeOrder
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
content:
|
||||
application/xml:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Order'
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Order'
|
||||
'400':
|
||||
description: Invalid Order
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Order'
|
||||
description: order placed for purchasing the pet
|
||||
required: true
|
||||
'/store/order/{orderId}':
|
||||
get:
|
||||
tags:
|
||||
- store
|
||||
summary: Find purchase order by ID
|
||||
description: >-
|
||||
For valid response try integer IDs with value <= 5 or > 10. Other values
|
||||
will generate exceptions
|
||||
operationId: getOrderById
|
||||
parameters:
|
||||
- name: orderId
|
||||
in: path
|
||||
description: ID of pet that needs to be fetched
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
minimum: 1
|
||||
maximum: 5
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
content:
|
||||
application/xml:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Order'
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Order'
|
||||
'400':
|
||||
description: Invalid ID supplied
|
||||
'404':
|
||||
description: Order not found
|
||||
delete:
|
||||
tags:
|
||||
- store
|
||||
summary: Delete purchase order by ID
|
||||
description: >-
|
||||
For valid response try integer IDs with value < 1000. Anything above
|
||||
1000 or nonintegers will generate API errors
|
||||
operationId: deleteOrder
|
||||
parameters:
|
||||
- name: orderId
|
||||
in: path
|
||||
description: ID of the order that needs to be deleted
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'400':
|
||||
description: Invalid ID supplied
|
||||
'404':
|
||||
description: Order not found
|
||||
/user:
|
||||
post:
|
||||
tags:
|
||||
- user
|
||||
summary: Create user
|
||||
description: This can only be done by the logged in user.
|
||||
operationId: createUser
|
||||
responses:
|
||||
default:
|
||||
description: successful operation
|
||||
security:
|
||||
- api_key: []
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/User'
|
||||
description: Created user object
|
||||
required: true
|
||||
/user/createWithArray:
|
||||
post:
|
||||
tags:
|
||||
- user
|
||||
summary: Creates list of users with given input array
|
||||
description: ''
|
||||
operationId: createUsersWithArrayInput
|
||||
responses:
|
||||
default:
|
||||
description: successful operation
|
||||
security:
|
||||
- api_key: []
|
||||
requestBody:
|
||||
$ref: '#/components/requestBodies/UserArray'
|
||||
/user/createWithList:
|
||||
post:
|
||||
tags:
|
||||
- user
|
||||
summary: Creates list of users with given input array
|
||||
description: ''
|
||||
operationId: createUsersWithListInput
|
||||
responses:
|
||||
default:
|
||||
description: successful operation
|
||||
security:
|
||||
- api_key: []
|
||||
requestBody:
|
||||
$ref: '#/components/requestBodies/UserArray'
|
||||
/user/login:
|
||||
get:
|
||||
tags:
|
||||
- user
|
||||
summary: Logs user into the system
|
||||
description: ''
|
||||
operationId: loginUser
|
||||
parameters:
|
||||
- name: username
|
||||
in: query
|
||||
description: The user name for login
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
pattern: '^[a-zA-Z0-9]+[a-zA-Z0-9\.\-_]*[a-zA-Z0-9]+$'
|
||||
- name: password
|
||||
in: query
|
||||
description: The password for login in clear text
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
headers:
|
||||
Set-Cookie:
|
||||
description: >-
|
||||
Cookie authentication key for use with the `api_key`
|
||||
apiKey authentication.
|
||||
schema:
|
||||
type: string
|
||||
example: AUTH_KEY=abcde12345; Path=/; HttpOnly
|
||||
X-Rate-Limit:
|
||||
description: calls per hour allowed by the user
|
||||
schema:
|
||||
type: integer
|
||||
format: int32
|
||||
X-Expires-After:
|
||||
description: date in UTC when token expires
|
||||
schema:
|
||||
type: string
|
||||
format: date-time
|
||||
content:
|
||||
application/xml:
|
||||
schema:
|
||||
type: string
|
||||
application/json:
|
||||
schema:
|
||||
type: string
|
||||
'400':
|
||||
description: Invalid username/password supplied
|
||||
/user/logout:
|
||||
get:
|
||||
tags:
|
||||
- user
|
||||
summary: Logs out current logged in user session
|
||||
description: ''
|
||||
operationId: logoutUser
|
||||
responses:
|
||||
default:
|
||||
description: successful operation
|
||||
security:
|
||||
- api_key: []
|
||||
'/user/{username}':
|
||||
get:
|
||||
tags:
|
||||
- user
|
||||
summary: Get user by user name
|
||||
description: ''
|
||||
operationId: getUserByName
|
||||
parameters:
|
||||
- name: username
|
||||
in: path
|
||||
description: The name that needs to be fetched. Use user1 for testing.
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
content:
|
||||
application/xml:
|
||||
schema:
|
||||
$ref: '#/components/schemas/User'
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/User'
|
||||
'400':
|
||||
description: Invalid username supplied
|
||||
'404':
|
||||
description: User not found
|
||||
put:
|
||||
tags:
|
||||
- user
|
||||
summary: Updated user
|
||||
description: This can only be done by the logged in user.
|
||||
operationId: updateUser
|
||||
parameters:
|
||||
- name: username
|
||||
in: path
|
||||
description: name that need to be deleted
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'400':
|
||||
description: Invalid user supplied
|
||||
'404':
|
||||
description: User not found
|
||||
security:
|
||||
- api_key: []
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/User'
|
||||
description: Updated user object
|
||||
required: true
|
||||
delete:
|
||||
tags:
|
||||
- user
|
||||
summary: Delete user
|
||||
description: This can only be done by the logged in user.
|
||||
operationId: deleteUser
|
||||
parameters:
|
||||
- name: username
|
||||
in: path
|
||||
description: The name that needs to be deleted
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'400':
|
||||
description: Invalid username supplied
|
||||
'404':
|
||||
description: User not found
|
||||
security:
|
||||
- api_key: []
|
||||
externalDocs:
|
||||
description: Find out more about Swagger
|
||||
url: 'http://swagger.io'
|
||||
components:
|
||||
requestBodies:
|
||||
UserArray:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/User'
|
||||
description: List of user object
|
||||
required: true
|
||||
Pet:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Pet'
|
||||
application/xml:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Pet'
|
||||
description: Pet object that needs to be added to the store
|
||||
required: true
|
||||
securitySchemes:
|
||||
petstore_auth:
|
||||
type: oauth2
|
||||
flows:
|
||||
implicit:
|
||||
authorizationUrl: 'http://petstore.swagger.io/api/oauth/dialog'
|
||||
scopes:
|
||||
'write:pets': modify pets in your account
|
||||
'read:pets': read your pets
|
||||
api_key:
|
||||
type: apiKey
|
||||
name: api_key
|
||||
in: header
|
||||
schemas:
|
||||
Order:
|
||||
title: Pet Order
|
||||
description: An order for a pets from the pet store
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
petId:
|
||||
type: integer
|
||||
format: int64
|
||||
quantity:
|
||||
type: integer
|
||||
format: int32
|
||||
shipDate:
|
||||
type: string
|
||||
format: date-time
|
||||
status:
|
||||
type: string
|
||||
description: Order Status
|
||||
enum:
|
||||
- placed
|
||||
- approved
|
||||
- delivered
|
||||
complete:
|
||||
type: boolean
|
||||
default: false
|
||||
xml:
|
||||
name: Order
|
||||
Category:
|
||||
title: Pet category
|
||||
description: A category for a pet
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
name:
|
||||
type: string
|
||||
pattern: '^[a-zA-Z0-9]+[a-zA-Z0-9\.\-_]*[a-zA-Z0-9]+$'
|
||||
xml:
|
||||
name: Category
|
||||
User:
|
||||
title: a User
|
||||
description: A User who is purchasing from the pet store
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
username:
|
||||
type: string
|
||||
firstName:
|
||||
type: string
|
||||
lastName:
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
password:
|
||||
type: string
|
||||
phone:
|
||||
type: string
|
||||
userStatus:
|
||||
type: integer
|
||||
format: int32
|
||||
description: User Status
|
||||
xml:
|
||||
name: User
|
||||
Tag:
|
||||
title: Pet Tag
|
||||
description: A tag for a pet
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
name:
|
||||
type: string
|
||||
xml:
|
||||
name: Tag
|
||||
Pet:
|
||||
title: a Pet
|
||||
description: A pet for sale in the pet store
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
- photoUrls
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
category:
|
||||
$ref: '#/components/schemas/Category'
|
||||
name:
|
||||
type: string
|
||||
example: doggie
|
||||
photoUrls:
|
||||
type: array
|
||||
xml:
|
||||
name: photoUrl
|
||||
wrapped: true
|
||||
items:
|
||||
type: string
|
||||
tags:
|
||||
type: array
|
||||
xml:
|
||||
name: tag
|
||||
wrapped: true
|
||||
items:
|
||||
$ref: '#/components/schemas/Tag'
|
||||
status:
|
||||
type: string
|
||||
description: pet status in the store
|
||||
deprecated: true
|
||||
enum:
|
||||
- available
|
||||
- pending
|
||||
- sold
|
||||
xml:
|
||||
name: Pet
|
||||
ApiResponse:
|
||||
title: An uploaded response
|
||||
description: Describes the result of uploading an image resource
|
||||
type: object
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
format: int32
|
||||
type:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
ComplexRequest:
|
||||
type: object
|
||||
required:
|
||||
- type
|
||||
- requiredField
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- someEnum
|
||||
requiredField:
|
||||
type: string
|
||||
description: A required string field
|
||||
stringField:
|
||||
type: string
|
||||
minLength: 5
|
||||
maxLength: 100
|
||||
description: String with length constraints
|
||||
integerField:
|
||||
type: integer
|
||||
minimum: 1
|
||||
maximum: 100
|
||||
description: Integer with a range from 1 to 100
|
||||
numberField:
|
||||
type: number
|
||||
exclusiveMinimum: 0.0
|
||||
exclusiveMaximum: 100.0
|
||||
description: Number with exclusive minimum and maximum constraints
|
||||
booleanField:
|
||||
type: boolean
|
||||
description: A boolean field
|
||||
emailField:
|
||||
type: string
|
||||
format: email
|
||||
description: A valid email address
|
||||
uuidField:
|
||||
type: string
|
||||
format: uuid
|
||||
description: A valid UUID
|
||||
dateField:
|
||||
type: string
|
||||
format: date
|
||||
description: A date field (YYYY-MM-DD)
|
||||
dateTimeField:
|
||||
type: string
|
||||
format: date-time
|
||||
description: A date-time field (RFC 3339 format)
|
||||
arrayField:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
minItems: 1
|
||||
maxItems: 10
|
||||
description: An array of strings with min and max items constraints
|
||||
enumField:
|
||||
type: string
|
||||
enum:
|
||||
- value1
|
||||
- value2
|
||||
- value3
|
||||
description: A string field with enum validation
|
||||
nestedObject:
|
||||
type: object
|
||||
properties:
|
||||
nestedField1:
|
||||
type: string
|
||||
description: A field within a nested object
|
||||
nestedField2:
|
||||
type: integer
|
||||
description: Another field in a nested object
|
||||
arrayOfObjectsField:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
objectField1:
|
||||
type: string
|
||||
objectField2:
|
||||
type: integer
|
||||
description: An array of objects
|
||||
patternField:
|
||||
type: string
|
||||
pattern: '^[a-zA-Z0-9]{3,10}$'
|
||||
description: A string field with regex pattern validation
|
||||
nullableField:
|
||||
type: string
|
||||
nullable: true
|
||||
description: A string field that allows null values
|
||||
additionalProperties:
|
||||
type: object
|
||||
description: Additional properties are allowed beyond the defined fields
|
||||
|
||||
AllOfRequest:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
age:
|
||||
type: integer
|
||||
details:
|
||||
allOf:
|
||||
- type: object
|
||||
properties:
|
||||
address:
|
||||
type: string
|
||||
- type: object
|
||||
properties:
|
||||
contact_number:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
- age
|
||||
SomeResponse1:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
required:
|
||||
- status
|
||||
- message
|
||||
|
||||
SomeResponse2:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
details:
|
||||
type: object
|
||||
properties:
|
||||
description:
|
||||
type: string
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
- created_at
|
@ -10,6 +10,8 @@ example/Server.scala
|
||||
jvm/src/main/scala/sample/cask/AppRoutes.scala
|
||||
jvm/src/main/scala/sample/cask/BaseApp.scala
|
||||
jvm/src/main/scala/sample/cask/ExampleApp.scala
|
||||
jvm/src/main/scala/sample/cask/api/ComplexRouteRoutes.scala
|
||||
jvm/src/main/scala/sample/cask/api/ComplexRouteRoutes.scala
|
||||
jvm/src/main/scala/sample/cask/api/OpenApiRoutes.scala
|
||||
jvm/src/main/scala/sample/cask/api/PetRoutes.scala
|
||||
jvm/src/main/scala/sample/cask/api/PetRoutes.scala
|
||||
@ -19,19 +21,50 @@ jvm/src/main/scala/sample/cask/api/UserRoutes.scala
|
||||
jvm/src/main/scala/sample/cask/api/UserRoutes.scala
|
||||
jvm/src/main/scala/sample/cask/api/package.scala
|
||||
jvm/src/main/scala/sample/cask/package.scala
|
||||
jvm/src/test/scala/sample/cask/model/AllOfRequestDetailsTest.scala
|
||||
jvm/src/test/scala/sample/cask/model/AllOfRequestTest.scala
|
||||
jvm/src/test/scala/sample/cask/model/ComplexRequestArrayOfObjectsFieldInnerTest.scala
|
||||
jvm/src/test/scala/sample/cask/model/ComplexRequestNestedObjectTest.scala
|
||||
jvm/src/test/scala/sample/cask/model/ComplexRequestTest.scala
|
||||
jvm/src/test/scala/sample/cask/model/OneOfRequestAndResponse200ResponseTest.scala
|
||||
jvm/src/test/scala/sample/cask/model/OneOfRequestAndResponseRequestTest.scala
|
||||
jvm/src/test/scala/sample/cask/model/SomeResponse1Test.scala
|
||||
jvm/src/test/scala/sample/cask/model/SomeResponse2DetailsTest.scala
|
||||
jvm/src/test/scala/sample/cask/model/SomeResponse2Test.scala
|
||||
project/build.properties
|
||||
project/plugins.sbt
|
||||
shared/src/main/scala/sample/cask/api/ComplexRouteService.scala
|
||||
shared/src/main/scala/sample/cask/api/PetService.scala
|
||||
shared/src/main/scala/sample/cask/api/StoreService.scala
|
||||
shared/src/main/scala/sample/cask/api/UserService.scala
|
||||
shared/src/main/scala/sample/cask/model/AllOfRequest.scala
|
||||
shared/src/main/scala/sample/cask/model/AllOfRequestData.scala
|
||||
shared/src/main/scala/sample/cask/model/AllOfRequestDetails.scala
|
||||
shared/src/main/scala/sample/cask/model/AllOfRequestDetailsData.scala
|
||||
shared/src/main/scala/sample/cask/model/ApiResponse.scala
|
||||
shared/src/main/scala/sample/cask/model/ApiResponseData.scala
|
||||
shared/src/main/scala/sample/cask/model/Category.scala
|
||||
shared/src/main/scala/sample/cask/model/CategoryData.scala
|
||||
shared/src/main/scala/sample/cask/model/ComplexRequest.scala
|
||||
shared/src/main/scala/sample/cask/model/ComplexRequestArrayOfObjectsFieldInner.scala
|
||||
shared/src/main/scala/sample/cask/model/ComplexRequestArrayOfObjectsFieldInnerData.scala
|
||||
shared/src/main/scala/sample/cask/model/ComplexRequestData.scala
|
||||
shared/src/main/scala/sample/cask/model/ComplexRequestNestedObject.scala
|
||||
shared/src/main/scala/sample/cask/model/ComplexRequestNestedObjectData.scala
|
||||
shared/src/main/scala/sample/cask/model/OneOfRequestAndResponse200Response.scala
|
||||
shared/src/main/scala/sample/cask/model/OneOfRequestAndResponse200ResponseData.scala
|
||||
shared/src/main/scala/sample/cask/model/OneOfRequestAndResponseRequest.scala
|
||||
shared/src/main/scala/sample/cask/model/OneOfRequestAndResponseRequestData.scala
|
||||
shared/src/main/scala/sample/cask/model/Order.scala
|
||||
shared/src/main/scala/sample/cask/model/OrderData.scala
|
||||
shared/src/main/scala/sample/cask/model/Pet.scala
|
||||
shared/src/main/scala/sample/cask/model/PetData.scala
|
||||
shared/src/main/scala/sample/cask/model/SomeResponse1.scala
|
||||
shared/src/main/scala/sample/cask/model/SomeResponse1Data.scala
|
||||
shared/src/main/scala/sample/cask/model/SomeResponse2.scala
|
||||
shared/src/main/scala/sample/cask/model/SomeResponse2Data.scala
|
||||
shared/src/main/scala/sample/cask/model/SomeResponse2Details.scala
|
||||
shared/src/main/scala/sample/cask/model/SomeResponse2DetailsData.scala
|
||||
shared/src/main/scala/sample/cask/model/Tag.scala
|
||||
shared/src/main/scala/sample/cask/model/TagData.scala
|
||||
shared/src/main/scala/sample/cask/model/User.scala
|
||||
|
@ -47,6 +47,7 @@ import sample.cask.model.*
|
||||
import java.io.File
|
||||
|
||||
// TODO - write your business logic for your services here (the defaults all return 'not implemented'):
|
||||
val myComplexRouteService : ComplexRouteService = ComplexRouteService() // <-- replace this with your implementation
|
||||
val myPetService : PetService = PetService() // <-- replace this with your implementation
|
||||
val myStoreService : StoreService = StoreService() // <-- replace this with your implementation
|
||||
val myUserService : UserService = UserService() // <-- replace this with your implementation
|
||||
@ -54,7 +55,8 @@ val myUserService : UserService = UserService() // <-- replace this with your im
|
||||
/** This is your main entry point for your REST service
|
||||
* It extends BaseApp which defines the business logic for your services
|
||||
*/
|
||||
object Server extends BaseApp(appPetService = myPetService,
|
||||
object Server extends BaseApp(appComplexRouteService = myComplexRouteService,
|
||||
appPetService = myPetService,
|
||||
appStoreService = myStoreService,
|
||||
appUserService = myUserService):
|
||||
start()
|
||||
|
@ -27,6 +27,35 @@
|
||||
"name" : "user"
|
||||
} ],
|
||||
"paths" : {
|
||||
"/complex-types" : {
|
||||
"post" : {
|
||||
"operationId" : "oneOfRequestAndResponse",
|
||||
"requestBody" : {
|
||||
"content" : {
|
||||
"application/json" : {
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/oneOfRequestAndResponse_request"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required" : true
|
||||
},
|
||||
"responses" : {
|
||||
"200" : {
|
||||
"content" : {
|
||||
"application/json" : {
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/oneOfRequestAndResponse_200_response"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description" : "Success"
|
||||
}
|
||||
},
|
||||
"summary" : "Example route with 'oneOf' content and response",
|
||||
"tags" : [ "complexRoute" ]
|
||||
}
|
||||
},
|
||||
"/pet" : {
|
||||
"post" : {
|
||||
"description" : "",
|
||||
@ -981,6 +1010,154 @@
|
||||
"title" : "An uploaded response",
|
||||
"type" : "object"
|
||||
},
|
||||
"ComplexRequest" : {
|
||||
"additionalProperties" : {
|
||||
"description" : "Additional properties are allowed beyond the defined fields",
|
||||
"type" : "object"
|
||||
},
|
||||
"properties" : {
|
||||
"type" : {
|
||||
"enum" : [ "someEnum" ],
|
||||
"type" : "string"
|
||||
},
|
||||
"requiredField" : {
|
||||
"description" : "A required string field",
|
||||
"type" : "string"
|
||||
},
|
||||
"stringField" : {
|
||||
"description" : "String with length constraints",
|
||||
"maxLength" : 100,
|
||||
"minLength" : 5,
|
||||
"type" : "string"
|
||||
},
|
||||
"integerField" : {
|
||||
"description" : "Integer with a range from 1 to 100",
|
||||
"maximum" : 100,
|
||||
"minimum" : 1,
|
||||
"type" : "integer"
|
||||
},
|
||||
"numberField" : {
|
||||
"description" : "Number with exclusive minimum and maximum constraints",
|
||||
"type" : "number"
|
||||
},
|
||||
"booleanField" : {
|
||||
"description" : "A boolean field",
|
||||
"type" : "boolean"
|
||||
},
|
||||
"emailField" : {
|
||||
"description" : "A valid email address",
|
||||
"format" : "email",
|
||||
"type" : "string"
|
||||
},
|
||||
"uuidField" : {
|
||||
"description" : "A valid UUID",
|
||||
"format" : "uuid",
|
||||
"type" : "string"
|
||||
},
|
||||
"dateField" : {
|
||||
"description" : "A date field (YYYY-MM-DD)",
|
||||
"format" : "date",
|
||||
"type" : "string"
|
||||
},
|
||||
"dateTimeField" : {
|
||||
"description" : "A date-time field (RFC 3339 format)",
|
||||
"format" : "date-time",
|
||||
"type" : "string"
|
||||
},
|
||||
"arrayField" : {
|
||||
"description" : "An array of strings with min and max items constraints",
|
||||
"items" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"maxItems" : 10,
|
||||
"minItems" : 1,
|
||||
"type" : "array"
|
||||
},
|
||||
"enumField" : {
|
||||
"description" : "A string field with enum validation",
|
||||
"enum" : [ "value1", "value2", "value3" ],
|
||||
"type" : "string"
|
||||
},
|
||||
"nestedObject" : {
|
||||
"$ref" : "#/components/schemas/ComplexRequest_nestedObject"
|
||||
},
|
||||
"arrayOfObjectsField" : {
|
||||
"items" : {
|
||||
"$ref" : "#/components/schemas/ComplexRequest_arrayOfObjectsField_inner"
|
||||
},
|
||||
"type" : "array"
|
||||
},
|
||||
"patternField" : {
|
||||
"description" : "A string field with regex pattern validation",
|
||||
"pattern" : "^[a-zA-Z0-9]{3,10}$",
|
||||
"type" : "string"
|
||||
},
|
||||
"nullableField" : {
|
||||
"description" : "A string field that allows null values",
|
||||
"nullable" : true,
|
||||
"type" : "string"
|
||||
}
|
||||
},
|
||||
"required" : [ "requiredField", "type" ],
|
||||
"type" : "object"
|
||||
},
|
||||
"AllOfRequest" : {
|
||||
"properties" : {
|
||||
"name" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"age" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"details" : {
|
||||
"$ref" : "#/components/schemas/AllOfRequest_details"
|
||||
}
|
||||
},
|
||||
"required" : [ "age", "name" ],
|
||||
"type" : "object"
|
||||
},
|
||||
"SomeResponse1" : {
|
||||
"properties" : {
|
||||
"status" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"message" : {
|
||||
"type" : "string"
|
||||
}
|
||||
},
|
||||
"required" : [ "message", "status" ],
|
||||
"type" : "object"
|
||||
},
|
||||
"SomeResponse2" : {
|
||||
"properties" : {
|
||||
"id" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"created_at" : {
|
||||
"format" : "date-time",
|
||||
"type" : "string"
|
||||
},
|
||||
"details" : {
|
||||
"$ref" : "#/components/schemas/SomeResponse2_details"
|
||||
}
|
||||
},
|
||||
"required" : [ "created_at", "id" ],
|
||||
"type" : "object"
|
||||
},
|
||||
"oneOfRequestAndResponse_request" : {
|
||||
"oneOf" : [ {
|
||||
"$ref" : "#/components/schemas/ComplexRequest"
|
||||
}, {
|
||||
"$ref" : "#/components/schemas/AllOfRequest"
|
||||
} ]
|
||||
},
|
||||
"oneOfRequestAndResponse_200_response" : {
|
||||
"oneOf" : [ {
|
||||
"$ref" : "#/components/schemas/SomeResponse1"
|
||||
}, {
|
||||
"$ref" : "#/components/schemas/SomeResponse2"
|
||||
} ]
|
||||
},
|
||||
"updatePetWithForm_request" : {
|
||||
"properties" : {
|
||||
"name" : {
|
||||
@ -1007,6 +1184,59 @@
|
||||
}
|
||||
},
|
||||
"type" : "object"
|
||||
},
|
||||
"ComplexRequest_nestedObject" : {
|
||||
"properties" : {
|
||||
"nestedField1" : {
|
||||
"description" : "A field within a nested object",
|
||||
"type" : "string"
|
||||
},
|
||||
"nestedField2" : {
|
||||
"description" : "Another field in a nested object",
|
||||
"type" : "integer"
|
||||
}
|
||||
},
|
||||
"type" : "object"
|
||||
},
|
||||
"ComplexRequest_arrayOfObjectsField_inner" : {
|
||||
"description" : "An array of objects",
|
||||
"properties" : {
|
||||
"objectField1" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"objectField2" : {
|
||||
"type" : "integer"
|
||||
}
|
||||
},
|
||||
"type" : "object"
|
||||
},
|
||||
"AllOfRequest_details" : {
|
||||
"allOf" : [ {
|
||||
"properties" : {
|
||||
"address" : {
|
||||
"type" : "string"
|
||||
}
|
||||
},
|
||||
"type" : "object"
|
||||
}, {
|
||||
"properties" : {
|
||||
"contact_number" : {
|
||||
"type" : "string"
|
||||
}
|
||||
},
|
||||
"type" : "object"
|
||||
} ]
|
||||
},
|
||||
"SomeResponse2_details" : {
|
||||
"properties" : {
|
||||
"description" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"status" : {
|
||||
"type" : "string"
|
||||
}
|
||||
},
|
||||
"type" : "object"
|
||||
}
|
||||
},
|
||||
"securitySchemes" : {
|
||||
|
@ -37,6 +37,9 @@ import _root_.sample.cask.api.*
|
||||
* More typically, however, you would extend the 'BaseApp' class
|
||||
*/
|
||||
trait AppRoutes {
|
||||
def appComplexRouteService : ComplexRouteService[Try] = ComplexRouteService()
|
||||
def routeForComplexRoute : ComplexRouteRoutes = ComplexRouteRoutes(appComplexRouteService)
|
||||
|
||||
def appPetService : PetService[Try] = PetService()
|
||||
def routeForPet : PetRoutes = PetRoutes(appPetService)
|
||||
|
||||
@ -48,6 +51,7 @@ trait AppRoutes {
|
||||
|
||||
|
||||
def appRoutes = Seq(
|
||||
routeForComplexRoute ,
|
||||
routeForPet ,
|
||||
routeForStore ,
|
||||
routeForUser
|
||||
|
@ -27,6 +27,8 @@ import _root_.sample.cask.api.*
|
||||
* passing in the custom business logic services
|
||||
*/
|
||||
class BaseApp(
|
||||
override val appComplexRouteService : ComplexRouteService[Try] = ComplexRouteService(),
|
||||
|
||||
override val appPetService : PetService[Try] = PetService(),
|
||||
|
||||
override val appStoreService : StoreService[Try] = StoreService(),
|
||||
|
@ -0,0 +1,59 @@
|
||||
//> using scala "3.3.1"
|
||||
//> using lib "com.lihaoyi::cask:0.8.3"
|
||||
//> using lib "com.lihaoyi::scalatags:0.12.0"
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
|
||||
// this is generated from apiRoutes.mustache
|
||||
package sample.cask.api
|
||||
|
||||
import sample.cask.model.*
|
||||
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
import scala.util.Try
|
||||
|
||||
import sample.cask.model.OneOfRequestAndResponse200Response
|
||||
import sample.cask.model.OneOfRequestAndResponseRequest
|
||||
|
||||
class ComplexRouteRoutes(service : ComplexRouteService[Try]) extends cask.Routes {
|
||||
|
||||
|
||||
/** Example route with 'oneOf' content and response
|
||||
*
|
||||
*/
|
||||
@cask.post("/complex-types")
|
||||
def oneOfRequestAndResponse(request: cask.Request) = {
|
||||
|
||||
def failFast = request.queryParams.keySet.contains("failFast")
|
||||
|
||||
val result = for {
|
||||
oneOfRequestAndResponseRequestJson <- Parsed.fromTry(request.bodyAsJson)
|
||||
oneOfRequestAndResponseRequestData <- Parsed.eval(OneOfRequestAndResponseRequestData.fromJson(oneOfRequestAndResponseRequestJson)) /* not array or map */
|
||||
oneOfRequestAndResponseRequest <- Parsed.fromTry(OneOfRequestAndResponseRequestData.validated(oneOfRequestAndResponseRequestData, failFast))
|
||||
resultTry <- Parsed.eval(service.oneOfRequestAndResponse(oneOfRequestAndResponseRequest))
|
||||
result <- Parsed.fromTry(resultTry)
|
||||
} yield result
|
||||
|
||||
import OneOfRequestAndResponse200Response.{given, *} // this brings in upickle in the case of union (oneOf) types
|
||||
|
||||
(result : @unchecked) match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(value : OneOfRequestAndResponse200Response) => cask.Response(data = write(value), 200, headers = Seq("Content-Type" -> "application/json"))
|
||||
case Right(other) => cask.Response(s"$other", 200)
|
||||
}
|
||||
}
|
||||
|
||||
initialize()
|
||||
}
|
@ -63,11 +63,13 @@ class PetRoutes(service : PetService[Try]) extends cask.Routes {
|
||||
val result = for {
|
||||
petJson <- Parsed.fromTry(request.bodyAsJson)
|
||||
petData <- Parsed.eval(PetData.fromJson(petJson)) /* not array or map */
|
||||
pet <- Parsed.fromTry(petData.validated(failFast))
|
||||
pet <- Parsed.fromTry(PetData.validated(petData, failFast))
|
||||
resultTry <- Parsed.eval(service.addPet(pet))
|
||||
result <- Parsed.fromTry(resultTry)
|
||||
} yield result
|
||||
|
||||
import Pet.{given, *} // this brings in upickle in the case of union (oneOf) types
|
||||
|
||||
(result : @unchecked) match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(value : Pet) => cask.Response(data = write(value), 200, headers = Seq("Content-Type" -> "application/json"))
|
||||
@ -90,6 +92,7 @@ class PetRoutes(service : PetService[Try]) extends cask.Routes {
|
||||
result <- Parsed.fromTry(resultTry)
|
||||
} yield result
|
||||
|
||||
|
||||
(result : @unchecked) match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(other) => cask.Response(s"$other", 200)
|
||||
@ -109,6 +112,7 @@ class PetRoutes(service : PetService[Try]) extends cask.Routes {
|
||||
result <- Parsed.fromTry(resultTry)
|
||||
} yield result
|
||||
|
||||
|
||||
(result : @unchecked) match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(value : List[Pet]) => cask.Response(data = write(value), 200, headers = Seq("Content-Type" -> "application/json"))
|
||||
@ -129,6 +133,7 @@ class PetRoutes(service : PetService[Try]) extends cask.Routes {
|
||||
result <- Parsed.fromTry(resultTry)
|
||||
} yield result
|
||||
|
||||
|
||||
(result : @unchecked) match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(value : List[Pet]) => cask.Response(data = write(value), 200, headers = Seq("Content-Type" -> "application/json"))
|
||||
@ -150,6 +155,8 @@ class PetRoutes(service : PetService[Try]) extends cask.Routes {
|
||||
result <- Parsed.fromTry(resultTry)
|
||||
} yield result
|
||||
|
||||
import Pet.{given, *} // this brings in upickle in the case of union (oneOf) types
|
||||
|
||||
(result : @unchecked) match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(value : Pet) => cask.Response(data = write(value), 200, headers = Seq("Content-Type" -> "application/json"))
|
||||
@ -168,11 +175,13 @@ class PetRoutes(service : PetService[Try]) extends cask.Routes {
|
||||
val result = for {
|
||||
petJson <- Parsed.fromTry(request.bodyAsJson)
|
||||
petData <- Parsed.eval(PetData.fromJson(petJson)) /* not array or map */
|
||||
pet <- Parsed.fromTry(petData.validated(failFast))
|
||||
pet <- Parsed.fromTry(PetData.validated(petData, failFast))
|
||||
resultTry <- Parsed.eval(service.updatePet(pet))
|
||||
result <- Parsed.fromTry(resultTry)
|
||||
} yield result
|
||||
|
||||
import Pet.{given, *} // this brings in upickle in the case of union (oneOf) types
|
||||
|
||||
(result : @unchecked) match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(value : Pet) => cask.Response(data = write(value), 200, headers = Seq("Content-Type" -> "application/json"))
|
||||
@ -196,6 +205,7 @@ class PetRoutes(service : PetService[Try]) extends cask.Routes {
|
||||
result <- Parsed.fromTry(resultTry)
|
||||
} yield result
|
||||
|
||||
|
||||
(result : @unchecked) match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(other) => cask.Response(s"$other", 200)
|
||||
@ -218,6 +228,8 @@ class PetRoutes(service : PetService[Try]) extends cask.Routes {
|
||||
result <- Parsed.fromTry(resultTry)
|
||||
} yield result
|
||||
|
||||
import ApiResponse.{given, *} // this brings in upickle in the case of union (oneOf) types
|
||||
|
||||
(result : @unchecked) match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(value : ApiResponse) => cask.Response(data = write(value), 200, headers = Seq("Content-Type" -> "application/json"))
|
||||
|
@ -43,6 +43,7 @@ class StoreRoutes(service : StoreService[Try]) extends cask.Routes {
|
||||
result <- Parsed.fromTry(resultTry)
|
||||
} yield result
|
||||
|
||||
|
||||
(result : @unchecked) match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(other) => cask.Response(s"$other", 200)
|
||||
@ -62,6 +63,7 @@ class StoreRoutes(service : StoreService[Try]) extends cask.Routes {
|
||||
result <- Parsed.fromTry(resultTry)
|
||||
} yield result
|
||||
|
||||
|
||||
(result : @unchecked) match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(value : Map[String, Int]) => cask.Response(data = write(value), 200, headers = Seq("Content-Type" -> "application/json"))
|
||||
@ -82,6 +84,8 @@ class StoreRoutes(service : StoreService[Try]) extends cask.Routes {
|
||||
result <- Parsed.fromTry(resultTry)
|
||||
} yield result
|
||||
|
||||
import Order.{given, *} // this brings in upickle in the case of union (oneOf) types
|
||||
|
||||
(result : @unchecked) match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(value : Order) => cask.Response(data = write(value), 200, headers = Seq("Content-Type" -> "application/json"))
|
||||
@ -99,11 +103,13 @@ class StoreRoutes(service : StoreService[Try]) extends cask.Routes {
|
||||
val result = for {
|
||||
orderJson <- Parsed.fromTry(request.bodyAsJson)
|
||||
orderData <- Parsed.eval(OrderData.fromJson(orderJson)) /* not array or map */
|
||||
order <- Parsed.fromTry(orderData.validated(failFast))
|
||||
order <- Parsed.fromTry(OrderData.validated(orderData, failFast))
|
||||
resultTry <- Parsed.eval(service.placeOrder(order))
|
||||
result <- Parsed.fromTry(resultTry)
|
||||
} yield result
|
||||
|
||||
import Order.{given, *} // this brings in upickle in the case of union (oneOf) types
|
||||
|
||||
(result : @unchecked) match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(value : Order) => cask.Response(data = write(value), 200, headers = Seq("Content-Type" -> "application/json"))
|
||||
|
@ -52,11 +52,12 @@ class UserRoutes(service : UserService[Try]) extends cask.Routes {
|
||||
val result = for {
|
||||
userJson <- Parsed.fromTry(request.bodyAsJson)
|
||||
userData <- Parsed.eval(UserData.fromJson(userJson)) /* not array or map */
|
||||
user <- Parsed.fromTry(userData.validated(failFast))
|
||||
user <- Parsed.fromTry(UserData.validated(userData, failFast))
|
||||
resultTry <- Parsed.eval(service.createUser(user))
|
||||
result <- Parsed.fromTry(resultTry)
|
||||
} yield result
|
||||
|
||||
|
||||
(result : @unchecked) match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(other) => cask.Response(s"$other", 200)
|
||||
@ -77,6 +78,7 @@ class UserRoutes(service : UserService[Try]) extends cask.Routes {
|
||||
result <- Parsed.fromTry(resultTry)
|
||||
} yield result
|
||||
|
||||
|
||||
(result : @unchecked) match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(other) => cask.Response(s"$other", 200)
|
||||
@ -97,6 +99,7 @@ class UserRoutes(service : UserService[Try]) extends cask.Routes {
|
||||
result <- Parsed.fromTry(resultTry)
|
||||
} yield result
|
||||
|
||||
|
||||
(result : @unchecked) match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(other) => cask.Response(s"$other", 200)
|
||||
@ -117,6 +120,7 @@ class UserRoutes(service : UserService[Try]) extends cask.Routes {
|
||||
result <- Parsed.fromTry(resultTry)
|
||||
} yield result
|
||||
|
||||
|
||||
(result : @unchecked) match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(other) => cask.Response(s"$other", 200)
|
||||
@ -136,6 +140,8 @@ class UserRoutes(service : UserService[Try]) extends cask.Routes {
|
||||
result <- Parsed.fromTry(resultTry)
|
||||
} yield result
|
||||
|
||||
import User.{given, *} // this brings in upickle in the case of union (oneOf) types
|
||||
|
||||
(result : @unchecked) match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(value : User) => cask.Response(data = write(value), 200, headers = Seq("Content-Type" -> "application/json"))
|
||||
@ -155,6 +161,7 @@ class UserRoutes(service : UserService[Try]) extends cask.Routes {
|
||||
result <- Parsed.fromTry(resultTry)
|
||||
} yield result
|
||||
|
||||
|
||||
(result : @unchecked) match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(value : String) => cask.Response(data = write(value), 200, headers = Seq("Content-Type" -> "application/json"))
|
||||
@ -175,6 +182,7 @@ class UserRoutes(service : UserService[Try]) extends cask.Routes {
|
||||
result <- Parsed.fromTry(resultTry)
|
||||
} yield result
|
||||
|
||||
|
||||
(result : @unchecked) match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(other) => cask.Response(s"$other", 200)
|
||||
@ -193,11 +201,12 @@ class UserRoutes(service : UserService[Try]) extends cask.Routes {
|
||||
username <- Parsed(username)
|
||||
userJson <- Parsed.fromTry(request.bodyAsJson)
|
||||
userData <- Parsed.eval(UserData.fromJson(userJson)) /* not array or map */
|
||||
user <- Parsed.fromTry(userData.validated(failFast))
|
||||
user <- Parsed.fromTry(UserData.validated(userData, failFast))
|
||||
resultTry <- Parsed.eval(service.updateUser(username, user))
|
||||
result <- Parsed.fromTry(resultTry)
|
||||
} yield result
|
||||
|
||||
|
||||
(result : @unchecked) match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(other) => cask.Response(s"$other", 200)
|
||||
|
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelTest.mustache
|
||||
package sample.cask.model
|
||||
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
import scala.util.*
|
||||
|
||||
class AllOfRequestDetailsTest extends AnyWordSpec with Matchers {
|
||||
|
||||
|
||||
"AllOfRequestDetails.fromJson" should {
|
||||
"""not parse invalid json""" in {
|
||||
val Failure(err) = Try(AllOfRequestDetailsData.fromJsonString("invalid jason"))
|
||||
err.getMessage should startWith ("Error parsing json 'invalid jason'")
|
||||
}
|
||||
"""parse """ ignore {
|
||||
val d8a = AllOfRequestDetailsData.fromJsonString("""""")
|
||||
val Failure(err : ValidationErrors) = AllOfRequestDetailsData.validated(d8a, true)
|
||||
|
||||
sys.error("TODO")
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelTest.mustache
|
||||
package sample.cask.model
|
||||
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
import scala.util.*
|
||||
|
||||
class AllOfRequestTest extends AnyWordSpec with Matchers {
|
||||
|
||||
|
||||
"AllOfRequest.fromJson" should {
|
||||
"""not parse invalid json""" in {
|
||||
val Failure(err) = Try(AllOfRequestData.fromJsonString("invalid jason"))
|
||||
err.getMessage should startWith ("Error parsing json 'invalid jason'")
|
||||
}
|
||||
"""parse """ ignore {
|
||||
val d8a = AllOfRequestData.fromJsonString("""""")
|
||||
val Failure(err : ValidationErrors) = AllOfRequestData.validated(d8a, true)
|
||||
|
||||
sys.error("TODO")
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelTest.mustache
|
||||
package sample.cask.model
|
||||
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
import scala.util.*
|
||||
|
||||
class ComplexRequestArrayOfObjectsFieldInnerTest extends AnyWordSpec with Matchers {
|
||||
|
||||
|
||||
"ComplexRequestArrayOfObjectsFieldInner.fromJson" should {
|
||||
"""not parse invalid json""" in {
|
||||
val Failure(err) = Try(ComplexRequestArrayOfObjectsFieldInnerData.fromJsonString("invalid jason"))
|
||||
err.getMessage should startWith ("Error parsing json 'invalid jason'")
|
||||
}
|
||||
"""parse """ ignore {
|
||||
val d8a = ComplexRequestArrayOfObjectsFieldInnerData.fromJsonString("""""")
|
||||
val Failure(err : ValidationErrors) = ComplexRequestArrayOfObjectsFieldInnerData.validated(d8a, true)
|
||||
|
||||
sys.error("TODO")
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelTest.mustache
|
||||
package sample.cask.model
|
||||
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
import scala.util.*
|
||||
|
||||
class ComplexRequestNestedObjectTest extends AnyWordSpec with Matchers {
|
||||
|
||||
|
||||
"ComplexRequestNestedObject.fromJson" should {
|
||||
"""not parse invalid json""" in {
|
||||
val Failure(err) = Try(ComplexRequestNestedObjectData.fromJsonString("invalid jason"))
|
||||
err.getMessage should startWith ("Error parsing json 'invalid jason'")
|
||||
}
|
||||
"""parse """ ignore {
|
||||
val d8a = ComplexRequestNestedObjectData.fromJsonString("""""")
|
||||
val Failure(err : ValidationErrors) = ComplexRequestNestedObjectData.validated(d8a, true)
|
||||
|
||||
sys.error("TODO")
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelTest.mustache
|
||||
package sample.cask.model
|
||||
import java.time.LocalDate
|
||||
import java.time.OffsetDateTime
|
||||
import java.util.UUID
|
||||
import scala.math.BigDecimal
|
||||
import ujson.Value
|
||||
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
import scala.util.*
|
||||
|
||||
class ComplexRequestTest extends AnyWordSpec with Matchers {
|
||||
|
||||
|
||||
"ComplexRequest.fromJson" should {
|
||||
"""not parse invalid json""" in {
|
||||
val Failure(err) = Try(ComplexRequestData.fromJsonString("invalid jason"))
|
||||
err.getMessage should startWith ("Error parsing json 'invalid jason'")
|
||||
}
|
||||
"""parse """ ignore {
|
||||
val d8a = ComplexRequestData.fromJsonString("""""")
|
||||
val Failure(err : ValidationErrors) = ComplexRequestData.validated(d8a, true)
|
||||
|
||||
sys.error("TODO")
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelTest.mustache
|
||||
package sample.cask.model
|
||||
import java.time.OffsetDateTime
|
||||
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
import scala.util.*
|
||||
|
||||
class OneOfRequestAndResponse200ResponseTest extends AnyWordSpec with Matchers {
|
||||
|
||||
|
||||
"OneOfRequestAndResponse200Response.fromJson" should {
|
||||
"""not parse invalid json""" in {
|
||||
val Failure(err) = Try(OneOfRequestAndResponse200ResponseData.fromJsonString("invalid jason"))
|
||||
err.getMessage should startWith ("Error parsing json 'invalid jason'")
|
||||
}
|
||||
"""parse """ ignore {
|
||||
val d8a = OneOfRequestAndResponse200ResponseData.fromJsonString("""""")
|
||||
val Failure(err : ValidationErrors) = OneOfRequestAndResponse200ResponseData.validated(d8a, true)
|
||||
|
||||
sys.error("TODO")
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelTest.mustache
|
||||
package sample.cask.model
|
||||
import java.time.LocalDate
|
||||
import java.time.OffsetDateTime
|
||||
import java.util.UUID
|
||||
import scala.math.BigDecimal
|
||||
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
import scala.util.*
|
||||
|
||||
class OneOfRequestAndResponseRequestTest extends AnyWordSpec with Matchers {
|
||||
|
||||
|
||||
"OneOfRequestAndResponseRequest.fromJson" should {
|
||||
"""not parse invalid json""" in {
|
||||
val Failure(err) = Try(OneOfRequestAndResponseRequestData.fromJsonString("invalid jason"))
|
||||
err.getMessage should startWith ("Error parsing json 'invalid jason'")
|
||||
}
|
||||
"""parse """ ignore {
|
||||
val d8a = OneOfRequestAndResponseRequestData.fromJsonString("""""")
|
||||
val Failure(err : ValidationErrors) = OneOfRequestAndResponseRequestData.validated(d8a, true)
|
||||
|
||||
sys.error("TODO")
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelTest.mustache
|
||||
package sample.cask.model
|
||||
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
import scala.util.*
|
||||
|
||||
class SomeResponse1Test extends AnyWordSpec with Matchers {
|
||||
|
||||
|
||||
"SomeResponse1.fromJson" should {
|
||||
"""not parse invalid json""" in {
|
||||
val Failure(err) = Try(SomeResponse1Data.fromJsonString("invalid jason"))
|
||||
err.getMessage should startWith ("Error parsing json 'invalid jason'")
|
||||
}
|
||||
"""parse """ ignore {
|
||||
val d8a = SomeResponse1Data.fromJsonString("""""")
|
||||
val Failure(err : ValidationErrors) = SomeResponse1Data.validated(d8a, true)
|
||||
|
||||
sys.error("TODO")
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelTest.mustache
|
||||
package sample.cask.model
|
||||
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
import scala.util.*
|
||||
|
||||
class SomeResponse2DetailsTest extends AnyWordSpec with Matchers {
|
||||
|
||||
|
||||
"SomeResponse2Details.fromJson" should {
|
||||
"""not parse invalid json""" in {
|
||||
val Failure(err) = Try(SomeResponse2DetailsData.fromJsonString("invalid jason"))
|
||||
err.getMessage should startWith ("Error parsing json 'invalid jason'")
|
||||
}
|
||||
"""parse """ ignore {
|
||||
val d8a = SomeResponse2DetailsData.fromJsonString("""""")
|
||||
val Failure(err : ValidationErrors) = SomeResponse2DetailsData.validated(d8a, true)
|
||||
|
||||
sys.error("TODO")
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelTest.mustache
|
||||
package sample.cask.model
|
||||
import java.time.OffsetDateTime
|
||||
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
import scala.util.*
|
||||
|
||||
class SomeResponse2Test extends AnyWordSpec with Matchers {
|
||||
|
||||
|
||||
"SomeResponse2.fromJson" should {
|
||||
"""not parse invalid json""" in {
|
||||
val Failure(err) = Try(SomeResponse2Data.fromJsonString("invalid jason"))
|
||||
err.getMessage should startWith ("Error parsing json 'invalid jason'")
|
||||
}
|
||||
"""parse """ ignore {
|
||||
val d8a = SomeResponse2Data.fromJsonString("""""")
|
||||
val Failure(err : ValidationErrors) = SomeResponse2Data.validated(d8a, true)
|
||||
|
||||
sys.error("TODO")
|
||||
}
|
||||
}
|
||||
}
|
@ -1 +1 @@
|
||||
sbt.version=1.9.9
|
||||
sbt.version=1.10.3
|
||||
|
@ -1,4 +1,4 @@
|
||||
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6")
|
||||
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "1.2.0")
|
||||
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.16.0")
|
||||
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.17.0")
|
||||
addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.2.0")
|
@ -0,0 +1,118 @@
|
||||
//> using scala "3.3.1"
|
||||
//> using lib "com.lihaoyi::cask:0.8.3"
|
||||
//> using lib "com.lihaoyi::scalatags:0.12.0"
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
|
||||
// generated from apiService.mustache
|
||||
package sample.cask.api
|
||||
|
||||
import _root_.sample.cask.model.OneOfRequestAndResponse200Response
|
||||
import _root_.sample.cask.model.OneOfRequestAndResponseRequest
|
||||
import scala.util.Failure
|
||||
import scala.util.Try
|
||||
import _root_.sample.cask.model.*
|
||||
|
||||
/**
|
||||
* The ComplexRouteService companion object.
|
||||
*
|
||||
* Use the ComplexRouteService() companion object to create an instance which returns a 'not implemented' error
|
||||
* for each operation.
|
||||
*
|
||||
*/
|
||||
object ComplexRouteService {
|
||||
|
||||
/**
|
||||
* The 'Handler' is an implementation of ComplexRouteService convenient for delegating or overriding individual functions
|
||||
*/
|
||||
case class Handler[F[_]](
|
||||
oneOfRequestAndResponseHandler : (oneOfRequestAndResponseRequest : OneOfRequestAndResponseRequest) => F[OneOfRequestAndResponse200Response]
|
||||
) extends ComplexRouteService[F] {
|
||||
|
||||
override def oneOfRequestAndResponse(oneOfRequestAndResponseRequest : OneOfRequestAndResponseRequest) : F[OneOfRequestAndResponse200Response] = {
|
||||
oneOfRequestAndResponseHandler(oneOfRequestAndResponseRequest)
|
||||
}
|
||||
}
|
||||
|
||||
def apply() : ComplexRouteService[Try] = ComplexRouteService.Handler[Try](
|
||||
(_) => notImplemented("oneOfRequestAndResponse")
|
||||
)
|
||||
|
||||
private def notImplemented(name : String) = Failure(new Exception(s"TODO: $name not implemented"))
|
||||
}
|
||||
|
||||
/**
|
||||
* The ComplexRoute business-logic
|
||||
*
|
||||
*
|
||||
* The 'asHandler' will return an implementation which allows for easily overriding individual operations.
|
||||
*
|
||||
* equally there are "on<Function>" helper methods for easily overriding individual functions
|
||||
*
|
||||
* @tparam F the effect type (Future, Try, IO, ID, etc) of the operations
|
||||
*/
|
||||
trait ComplexRouteService[F[_]] {
|
||||
/** Example route with 'oneOf' content and response
|
||||
*
|
||||
* @return OneOfRequestAndResponse200Response
|
||||
*/
|
||||
def oneOfRequestAndResponse(oneOfRequestAndResponseRequest : OneOfRequestAndResponseRequest) : F[OneOfRequestAndResponse200Response]
|
||||
|
||||
/**
|
||||
* override oneOfRequestAndResponse with the given handler
|
||||
* @return a new implementation of ComplexRouteService[F] with oneOfRequestAndResponse overridden using the given handler
|
||||
*/
|
||||
final def onOneOfRequestAndResponse(handler : (oneOfRequestAndResponseRequest : OneOfRequestAndResponseRequest) => F[OneOfRequestAndResponse200Response]) : ComplexRouteService[F] = {
|
||||
asHandler.copy(oneOfRequestAndResponseHandler = handler)
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a Handler implementation of this service
|
||||
*/
|
||||
final def asHandler : ComplexRouteService.Handler[F] = this match {
|
||||
case h : ComplexRouteService.Handler[F] => h
|
||||
case _ =>
|
||||
ComplexRouteService.Handler[F](
|
||||
(oneOfRequestAndResponseRequest) => oneOfRequestAndResponse(oneOfRequestAndResponseRequest)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will change the effect type of this service.
|
||||
*
|
||||
* It's not unlike a typical map operation from A => B, except we're not mapping
|
||||
* a type from A to B, but rather from F[A] => G[A] using the 'changeEffect' function.
|
||||
*
|
||||
* For, this could turn an asynchronous service (one which returns Future[_] types) into
|
||||
* a synchronous one (one which returns Try[_] types) by awaiting on the Future.
|
||||
*
|
||||
* It could change an IO type (like cats effect or ZIO) into an ID[A] which is just:
|
||||
* ```
|
||||
* type ID[A] => A
|
||||
* ```
|
||||
*
|
||||
* @tparam G the new "polymorphic" effect type
|
||||
* @param changeEffect the "natural transformation" which can change one effect type into another
|
||||
* @return a new ComplexRouteService service implementation with effect type [G]
|
||||
*/
|
||||
final def mapEffect[G[_]](changeEffect : [A] => F[A] => G[A]) : ComplexRouteService[G] = {
|
||||
val self = this
|
||||
|
||||
new ComplexRouteService[G] {
|
||||
override def oneOfRequestAndResponse(oneOfRequestAndResponseRequest : OneOfRequestAndResponseRequest) : G[OneOfRequestAndResponse200Response] = changeEffect {
|
||||
self.oneOfRequestAndResponse(oneOfRequestAndResponseRequest)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using model.mustache
|
||||
package sample.cask.model
|
||||
|
||||
import scala.util.control.NonFatal
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
|
||||
case class AllOfRequest(
|
||||
name: String,
|
||||
age: Int,
|
||||
details: Option[AllOfRequestDetails] = None
|
||||
|
||||
|
||||
) {
|
||||
|
||||
def asJsonString: String = asData.asJsonString
|
||||
def asJson: ujson.Value = asData.asJson
|
||||
|
||||
def asData : AllOfRequestData = {
|
||||
AllOfRequestData(
|
||||
name = name /* 2 */,
|
||||
age = age /* 2 */,
|
||||
details = details.map(_.asData).getOrElse(null) /* 4 */
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object AllOfRequest {
|
||||
given RW[AllOfRequest] = summon[RW[ujson.Value]].bimap[AllOfRequest](_.asJson, json => read[AllOfRequestData](json).asModel)
|
||||
|
||||
enum Fields(val fieldName : String) extends Field(fieldName) {
|
||||
case name extends Fields("name")
|
||||
case age extends Fields("age")
|
||||
case details extends Fields("details")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,149 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelData.mustache
|
||||
package sample.cask.model
|
||||
import scala.util.control.NonFatal
|
||||
import scala.util.*
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
/** AllOfRequestData a data transfer object, primarily for simple json serialisation.
|
||||
* It has no validation - there may be nulls, values out of range, etc
|
||||
*/
|
||||
case class AllOfRequestData(
|
||||
name: String,
|
||||
age: Int,
|
||||
details: AllOfRequestDetailsData = null
|
||||
|
||||
|
||||
) derives RW {
|
||||
|
||||
def asJsonString: String = asJson.toString()
|
||||
|
||||
def asJson : ujson.Value = {
|
||||
val jason = writeJs(this)
|
||||
jason
|
||||
}
|
||||
|
||||
def validationErrors(path : Seq[Field], failFast : Boolean) : Seq[ValidationError] = {
|
||||
val _allValidationErrors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
// ================== name validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ================== age validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ================== details validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
// validating details
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
if details != null then _allValidationErrors ++= details.validationErrors(path :+ AllOfRequest.Fields.details, failFast)
|
||||
}
|
||||
|
||||
_allValidationErrors.toSeq
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the validated model within a Try (if successful)
|
||||
*/
|
||||
def validated(failFast : Boolean = false) : scala.util.Try[AllOfRequest] = {
|
||||
validationErrors(Vector(), failFast) match {
|
||||
case Seq() => Success(asModel)
|
||||
case first +: theRest => Failure(ValidationErrors(first, theRest))
|
||||
}
|
||||
}
|
||||
|
||||
/** use 'validated' to check validation */
|
||||
def asModel : AllOfRequest = {
|
||||
AllOfRequest(
|
||||
name = name /* 2 */,
|
||||
age = age /* 2 */,
|
||||
details = Option(details).map(_.asModel) /* 4 */
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object AllOfRequestData {
|
||||
|
||||
def validated(d8a : AllOfRequestData, failFast : Boolean) : scala.util.Try[AllOfRequest] = d8a.validated(failFast)
|
||||
|
||||
def fromJson(jason : ujson.Value) : AllOfRequestData = try {
|
||||
val data = read[AllOfRequestData](jason)
|
||||
data
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error creating AllOfRequestData from json '$jason': $e")
|
||||
}
|
||||
|
||||
def fromJsonString(jason : String) : AllOfRequestData = {
|
||||
val parsed = try {
|
||||
read[ujson.Value](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason': $e")
|
||||
}
|
||||
fromJson(parsed)
|
||||
}
|
||||
|
||||
def manyFromJsonString(jason : String) : Seq[AllOfRequestData] = try {
|
||||
read[List[AllOfRequestData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as list: $e")
|
||||
}
|
||||
|
||||
def manyFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Seq[AllOfRequest]] = {
|
||||
Try(manyFromJsonString(jason)).flatMap { list =>
|
||||
list.zipWithIndex.foldLeft(Try(Vector[AllOfRequest]())) {
|
||||
case (Success(list), (next, i)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(list :+ ok)
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $i: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def mapFromJsonString(jason : String) : Map[String, AllOfRequestData] = try {
|
||||
read[Map[String, AllOfRequestData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as map: $e")
|
||||
}
|
||||
|
||||
|
||||
def mapFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Map[String, AllOfRequest]] = {
|
||||
Try(mapFromJsonString(jason)).flatMap { map =>
|
||||
map.foldLeft(Try(Map[String, AllOfRequest]())) {
|
||||
case (Success(map), (key, next)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(map.updated(key, ok))
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $key: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using model.mustache
|
||||
package sample.cask.model
|
||||
|
||||
import scala.util.control.NonFatal
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
|
||||
case class AllOfRequestDetails(
|
||||
address: Option[String] = None ,
|
||||
contactNumber: Option[String] = None
|
||||
|
||||
|
||||
) {
|
||||
|
||||
def asJsonString: String = asData.asJsonString
|
||||
def asJson: ujson.Value = asData.asJson
|
||||
|
||||
def asData : AllOfRequestDetailsData = {
|
||||
AllOfRequestDetailsData(
|
||||
address = address.getOrElse("") /* 1 */,
|
||||
contactNumber = contactNumber.getOrElse("") /* 1 */
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object AllOfRequestDetails {
|
||||
given RW[AllOfRequestDetails] = summon[RW[ujson.Value]].bimap[AllOfRequestDetails](_.asJson, json => read[AllOfRequestDetailsData](json).asModel)
|
||||
|
||||
enum Fields(val fieldName : String) extends Field(fieldName) {
|
||||
case address extends Fields("address")
|
||||
case contactNumber extends Fields("contactNumber")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,137 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelData.mustache
|
||||
package sample.cask.model
|
||||
import scala.util.control.NonFatal
|
||||
import scala.util.*
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
/** AllOfRequestDetailsData a data transfer object, primarily for simple json serialisation.
|
||||
* It has no validation - there may be nulls, values out of range, etc
|
||||
*/
|
||||
case class AllOfRequestDetailsData(
|
||||
address: String = "" ,
|
||||
contactNumber: String = ""
|
||||
|
||||
|
||||
) derives RW {
|
||||
|
||||
def asJsonString: String = asJson.toString()
|
||||
|
||||
def asJson : ujson.Value = {
|
||||
val jason = writeJs(this)
|
||||
jason
|
||||
}
|
||||
|
||||
def validationErrors(path : Seq[Field], failFast : Boolean) : Seq[ValidationError] = {
|
||||
val _allValidationErrors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
// ================== address validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ================== contactNumber validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
_allValidationErrors.toSeq
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the validated model within a Try (if successful)
|
||||
*/
|
||||
def validated(failFast : Boolean = false) : scala.util.Try[AllOfRequestDetails] = {
|
||||
validationErrors(Vector(), failFast) match {
|
||||
case Seq() => Success(asModel)
|
||||
case first +: theRest => Failure(ValidationErrors(first, theRest))
|
||||
}
|
||||
}
|
||||
|
||||
/** use 'validated' to check validation */
|
||||
def asModel : AllOfRequestDetails = {
|
||||
AllOfRequestDetails(
|
||||
address = Option(address) /* 1 */,
|
||||
contactNumber = Option(contactNumber) /* 1 */
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object AllOfRequestDetailsData {
|
||||
|
||||
def validated(d8a : AllOfRequestDetailsData, failFast : Boolean) : scala.util.Try[AllOfRequestDetails] = d8a.validated(failFast)
|
||||
|
||||
def fromJson(jason : ujson.Value) : AllOfRequestDetailsData = try {
|
||||
val data = read[AllOfRequestDetailsData](jason)
|
||||
data
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error creating AllOfRequestDetailsData from json '$jason': $e")
|
||||
}
|
||||
|
||||
def fromJsonString(jason : String) : AllOfRequestDetailsData = {
|
||||
val parsed = try {
|
||||
read[ujson.Value](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason': $e")
|
||||
}
|
||||
fromJson(parsed)
|
||||
}
|
||||
|
||||
def manyFromJsonString(jason : String) : Seq[AllOfRequestDetailsData] = try {
|
||||
read[List[AllOfRequestDetailsData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as list: $e")
|
||||
}
|
||||
|
||||
def manyFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Seq[AllOfRequestDetails]] = {
|
||||
Try(manyFromJsonString(jason)).flatMap { list =>
|
||||
list.zipWithIndex.foldLeft(Try(Vector[AllOfRequestDetails]())) {
|
||||
case (Success(list), (next, i)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(list :+ ok)
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $i: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def mapFromJsonString(jason : String) : Map[String, AllOfRequestDetailsData] = try {
|
||||
read[Map[String, AllOfRequestDetailsData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as map: $e")
|
||||
}
|
||||
|
||||
|
||||
def mapFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Map[String, AllOfRequestDetails]] = {
|
||||
Try(mapFromJsonString(jason)).flatMap { map =>
|
||||
map.foldLeft(Try(Map[String, AllOfRequestDetails]())) {
|
||||
case (Success(map), (key, next)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(map.updated(key, ok))
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $key: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
|
||||
|
||||
case class ApiResponse(
|
||||
code: Option[Int] = None ,
|
||||
`type`: Option[String] = None ,
|
||||
@ -55,3 +55,4 @@ enum Fields(val fieldName : String) extends Field(fieldName) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -40,7 +40,7 @@ case class ApiResponseData(
|
||||
}
|
||||
|
||||
def validationErrors(path : Seq[Field], failFast : Boolean) : Seq[ValidationError] = {
|
||||
val errors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
val _allValidationErrors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
// ================== code validation ==================
|
||||
|
||||
|
||||
@ -59,7 +59,7 @@ case class ApiResponseData(
|
||||
|
||||
|
||||
|
||||
errors.toSeq
|
||||
_allValidationErrors.toSeq
|
||||
}
|
||||
|
||||
/**
|
||||
@ -85,6 +85,8 @@ case class ApiResponseData(
|
||||
|
||||
object ApiResponseData {
|
||||
|
||||
def validated(d8a : ApiResponseData, failFast : Boolean) : scala.util.Try[ApiResponse] = d8a.validated(failFast)
|
||||
|
||||
def fromJson(jason : ujson.Value) : ApiResponseData = try {
|
||||
val data = read[ApiResponseData](jason)
|
||||
data
|
||||
|
@ -21,7 +21,7 @@ import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
|
||||
|
||||
case class Category(
|
||||
id: Option[Long] = None ,
|
||||
name: Option[String] = None
|
||||
@ -52,3 +52,4 @@ enum Fields(val fieldName : String) extends Field(fieldName) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -39,7 +39,7 @@ case class CategoryData(
|
||||
}
|
||||
|
||||
def validationErrors(path : Seq[Field], failFast : Boolean) : Seq[ValidationError] = {
|
||||
val errors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
val _allValidationErrors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
// ================== id validation ==================
|
||||
|
||||
|
||||
@ -48,17 +48,17 @@ case class CategoryData(
|
||||
|
||||
// ================== name validation ==================
|
||||
// validate against pattern '^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$'
|
||||
if (errors.isEmpty || !failFast) {
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
val regex = """^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$"""
|
||||
if name == null || !regex.r.matches(name) then
|
||||
errors += ValidationError(path :+ Category.Fields.name, s"value '$name' doesn't match pattern $regex")
|
||||
_allValidationErrors += ValidationError(path :+ Category.Fields.name, s"value '$name' doesn't match pattern $regex")
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
errors.toSeq
|
||||
_allValidationErrors.toSeq
|
||||
}
|
||||
|
||||
/**
|
||||
@ -83,6 +83,8 @@ case class CategoryData(
|
||||
|
||||
object CategoryData {
|
||||
|
||||
def validated(d8a : CategoryData, failFast : Boolean) : scala.util.Try[Category] = d8a.validated(failFast)
|
||||
|
||||
def fromJson(jason : ujson.Value) : CategoryData = try {
|
||||
val data = read[CategoryData](jason)
|
||||
data
|
||||
|
@ -0,0 +1,127 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using model.mustache
|
||||
package sample.cask.model
|
||||
import java.time.LocalDate
|
||||
import java.time.OffsetDateTime
|
||||
import java.util.UUID
|
||||
import scala.math.BigDecimal
|
||||
import ujson.Value
|
||||
|
||||
import scala.util.control.NonFatal
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
|
||||
case class ComplexRequest(
|
||||
`type`: ComplexRequest.TypeEnum,
|
||||
/* A required string field */
|
||||
requiredField: String,
|
||||
/* String with length constraints */
|
||||
stringField: Option[String] = None ,
|
||||
/* Integer with a range from 1 to 100 */
|
||||
integerField: Option[Int] = None ,
|
||||
/* Number with exclusive minimum and maximum constraints */
|
||||
numberField: Option[BigDecimal] = None ,
|
||||
/* A boolean field */
|
||||
booleanField: Option[Boolean] = None ,
|
||||
/* A valid email address */
|
||||
emailField: Option[String] = None ,
|
||||
/* A valid UUID */
|
||||
uuidField: Option[UUID] = None ,
|
||||
/* A date field (YYYY-MM-DD) */
|
||||
dateField: Option[LocalDate] = None ,
|
||||
/* A date-time field (RFC 3339 format) */
|
||||
dateTimeField: Option[OffsetDateTime] = None ,
|
||||
/* An array of strings with min and max items constraints */
|
||||
arrayField: Seq[String] = Nil ,
|
||||
/* A string field with enum validation */
|
||||
enumField: Option[ComplexRequest.EnumFieldEnum] = None ,
|
||||
nestedObject: Option[ComplexRequestNestedObject] = None ,
|
||||
arrayOfObjectsField: Seq[ComplexRequestArrayOfObjectsFieldInner] = Nil ,
|
||||
/* A string field with regex pattern validation */
|
||||
patternField: Option[String] = None ,
|
||||
/* A string field that allows null values */
|
||||
nullableField: Option[String] = None
|
||||
|
||||
, additionalProperties : ujson.Value = ujson.Null
|
||||
) {
|
||||
|
||||
def asJsonString: String = asData.asJsonString
|
||||
def asJson: ujson.Value = asData.asJson
|
||||
|
||||
def asData : ComplexRequestData = {
|
||||
ComplexRequestData(
|
||||
`type` = `type` /* 2 */,
|
||||
requiredField = requiredField /* 2 */,
|
||||
stringField = stringField.getOrElse("") /* 1 */,
|
||||
integerField = integerField.getOrElse(0) /* 1 */,
|
||||
numberField = numberField.getOrElse(0) /* 1 */,
|
||||
booleanField = booleanField.getOrElse(false) /* 1 */,
|
||||
emailField = emailField.getOrElse("") /* 1 */,
|
||||
uuidField = uuidField.getOrElse(java.util.UUID.randomUUID()) /* 1 */,
|
||||
dateField = dateField.getOrElse(null) /* 1 */,
|
||||
dateTimeField = dateTimeField.getOrElse(null) /* 1 */,
|
||||
arrayField = arrayField /* 2 */,
|
||||
enumField = enumField.getOrElse(null) /* 1 */,
|
||||
nestedObject = nestedObject.map(_.asData).getOrElse(null) /* 4 */,
|
||||
arrayOfObjectsField = arrayOfObjectsField.map(_.asData) /* 6 */,
|
||||
patternField = patternField.getOrElse("") /* 1 */,
|
||||
nullableField = nullableField.getOrElse("") /* 1 */
|
||||
, additionalProperties
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object ComplexRequest {
|
||||
given RW[ComplexRequest] = summon[RW[ujson.Value]].bimap[ComplexRequest](_.asJson, json => read[ComplexRequestData](json).asModel)
|
||||
|
||||
enum Fields(val fieldName : String) extends Field(fieldName) {
|
||||
case `type` extends Fields("`type`")
|
||||
case requiredField extends Fields("requiredField")
|
||||
case stringField extends Fields("stringField")
|
||||
case integerField extends Fields("integerField")
|
||||
case numberField extends Fields("numberField")
|
||||
case booleanField extends Fields("booleanField")
|
||||
case emailField extends Fields("emailField")
|
||||
case uuidField extends Fields("uuidField")
|
||||
case dateField extends Fields("dateField")
|
||||
case dateTimeField extends Fields("dateTimeField")
|
||||
case arrayField extends Fields("arrayField")
|
||||
case enumField extends Fields("enumField")
|
||||
case nestedObject extends Fields("nestedObject")
|
||||
case arrayOfObjectsField extends Fields("arrayOfObjectsField")
|
||||
case patternField extends Fields("patternField")
|
||||
case nullableField extends Fields("nullableField")
|
||||
}
|
||||
|
||||
// baseName=type
|
||||
// nameInCamelCase = `type`
|
||||
enum TypeEnum derives ReadWriter {
|
||||
case someEnum
|
||||
}
|
||||
// baseName=enumField
|
||||
// nameInCamelCase = enumField
|
||||
enum EnumFieldEnum derives ReadWriter {
|
||||
case value1
|
||||
case value2
|
||||
case value3
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using model.mustache
|
||||
package sample.cask.model
|
||||
|
||||
import scala.util.control.NonFatal
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
|
||||
case class ComplexRequestArrayOfObjectsFieldInner(
|
||||
objectField1: Option[String] = None ,
|
||||
objectField2: Option[Int] = None
|
||||
|
||||
|
||||
) {
|
||||
|
||||
def asJsonString: String = asData.asJsonString
|
||||
def asJson: ujson.Value = asData.asJson
|
||||
|
||||
def asData : ComplexRequestArrayOfObjectsFieldInnerData = {
|
||||
ComplexRequestArrayOfObjectsFieldInnerData(
|
||||
objectField1 = objectField1.getOrElse("") /* 1 */,
|
||||
objectField2 = objectField2.getOrElse(0) /* 1 */
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object ComplexRequestArrayOfObjectsFieldInner {
|
||||
given RW[ComplexRequestArrayOfObjectsFieldInner] = summon[RW[ujson.Value]].bimap[ComplexRequestArrayOfObjectsFieldInner](_.asJson, json => read[ComplexRequestArrayOfObjectsFieldInnerData](json).asModel)
|
||||
|
||||
enum Fields(val fieldName : String) extends Field(fieldName) {
|
||||
case objectField1 extends Fields("objectField1")
|
||||
case objectField2 extends Fields("objectField2")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,137 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelData.mustache
|
||||
package sample.cask.model
|
||||
import scala.util.control.NonFatal
|
||||
import scala.util.*
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
/** ComplexRequestArrayOfObjectsFieldInnerData a data transfer object, primarily for simple json serialisation.
|
||||
* It has no validation - there may be nulls, values out of range, etc
|
||||
*/
|
||||
case class ComplexRequestArrayOfObjectsFieldInnerData(
|
||||
objectField1: String = "" ,
|
||||
objectField2: Int = 0
|
||||
|
||||
|
||||
) derives RW {
|
||||
|
||||
def asJsonString: String = asJson.toString()
|
||||
|
||||
def asJson : ujson.Value = {
|
||||
val jason = writeJs(this)
|
||||
jason
|
||||
}
|
||||
|
||||
def validationErrors(path : Seq[Field], failFast : Boolean) : Seq[ValidationError] = {
|
||||
val _allValidationErrors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
// ================== objectField1 validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ================== objectField2 validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
_allValidationErrors.toSeq
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the validated model within a Try (if successful)
|
||||
*/
|
||||
def validated(failFast : Boolean = false) : scala.util.Try[ComplexRequestArrayOfObjectsFieldInner] = {
|
||||
validationErrors(Vector(), failFast) match {
|
||||
case Seq() => Success(asModel)
|
||||
case first +: theRest => Failure(ValidationErrors(first, theRest))
|
||||
}
|
||||
}
|
||||
|
||||
/** use 'validated' to check validation */
|
||||
def asModel : ComplexRequestArrayOfObjectsFieldInner = {
|
||||
ComplexRequestArrayOfObjectsFieldInner(
|
||||
objectField1 = Option(objectField1) /* 1 */,
|
||||
objectField2 = Option(objectField2) /* 1 */
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object ComplexRequestArrayOfObjectsFieldInnerData {
|
||||
|
||||
def validated(d8a : ComplexRequestArrayOfObjectsFieldInnerData, failFast : Boolean) : scala.util.Try[ComplexRequestArrayOfObjectsFieldInner] = d8a.validated(failFast)
|
||||
|
||||
def fromJson(jason : ujson.Value) : ComplexRequestArrayOfObjectsFieldInnerData = try {
|
||||
val data = read[ComplexRequestArrayOfObjectsFieldInnerData](jason)
|
||||
data
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error creating ComplexRequestArrayOfObjectsFieldInnerData from json '$jason': $e")
|
||||
}
|
||||
|
||||
def fromJsonString(jason : String) : ComplexRequestArrayOfObjectsFieldInnerData = {
|
||||
val parsed = try {
|
||||
read[ujson.Value](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason': $e")
|
||||
}
|
||||
fromJson(parsed)
|
||||
}
|
||||
|
||||
def manyFromJsonString(jason : String) : Seq[ComplexRequestArrayOfObjectsFieldInnerData] = try {
|
||||
read[List[ComplexRequestArrayOfObjectsFieldInnerData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as list: $e")
|
||||
}
|
||||
|
||||
def manyFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Seq[ComplexRequestArrayOfObjectsFieldInner]] = {
|
||||
Try(manyFromJsonString(jason)).flatMap { list =>
|
||||
list.zipWithIndex.foldLeft(Try(Vector[ComplexRequestArrayOfObjectsFieldInner]())) {
|
||||
case (Success(list), (next, i)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(list :+ ok)
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $i: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def mapFromJsonString(jason : String) : Map[String, ComplexRequestArrayOfObjectsFieldInnerData] = try {
|
||||
read[Map[String, ComplexRequestArrayOfObjectsFieldInnerData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as map: $e")
|
||||
}
|
||||
|
||||
|
||||
def mapFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Map[String, ComplexRequestArrayOfObjectsFieldInner]] = {
|
||||
Try(mapFromJsonString(jason)).flatMap { map =>
|
||||
map.foldLeft(Try(Map[String, ComplexRequestArrayOfObjectsFieldInner]())) {
|
||||
case (Success(map), (key, next)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(map.updated(key, ok))
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $key: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,338 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelData.mustache
|
||||
package sample.cask.model
|
||||
import java.time.LocalDate
|
||||
import java.time.OffsetDateTime
|
||||
import java.util.UUID
|
||||
import scala.math.BigDecimal
|
||||
import ujson.Value
|
||||
import scala.util.control.NonFatal
|
||||
import scala.util.*
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
/** ComplexRequestData a data transfer object, primarily for simple json serialisation.
|
||||
* It has no validation - there may be nulls, values out of range, etc
|
||||
*/
|
||||
case class ComplexRequestData(
|
||||
`type`: ComplexRequest.TypeEnum,
|
||||
/* A required string field */
|
||||
requiredField: String,
|
||||
/* String with length constraints */
|
||||
stringField: String = "" ,
|
||||
/* Integer with a range from 1 to 100 */
|
||||
integerField: Int = 0 ,
|
||||
/* Number with exclusive minimum and maximum constraints */
|
||||
numberField: BigDecimal = 0 ,
|
||||
/* A boolean field */
|
||||
booleanField: Boolean = false ,
|
||||
/* A valid email address */
|
||||
emailField: String = "" ,
|
||||
/* A valid UUID */
|
||||
uuidField: UUID = java.util.UUID.randomUUID() ,
|
||||
/* A date field (YYYY-MM-DD) */
|
||||
dateField: LocalDate = null ,
|
||||
/* A date-time field (RFC 3339 format) */
|
||||
dateTimeField: OffsetDateTime = null ,
|
||||
/* An array of strings with min and max items constraints */
|
||||
arrayField: Seq[String] = Nil ,
|
||||
/* A string field with enum validation */
|
||||
enumField: ComplexRequest.EnumFieldEnum = null ,
|
||||
nestedObject: ComplexRequestNestedObjectData = null ,
|
||||
arrayOfObjectsField: Seq[ComplexRequestArrayOfObjectsFieldInnerData] = Nil ,
|
||||
/* A string field with regex pattern validation */
|
||||
patternField: String = "" ,
|
||||
/* A string field that allows null values */
|
||||
nullableField: String = ""
|
||||
, additionalProperties : ujson.Value = ujson.Null
|
||||
|
||||
) derives RW {
|
||||
|
||||
def asJsonString: String = asJson.toString()
|
||||
|
||||
def asJson : ujson.Value = {
|
||||
val jason = writeJs(this)
|
||||
jason.obj.remove("additionalProperties")
|
||||
jason.mergeWith(additionalProperties)
|
||||
}
|
||||
|
||||
def validationErrors(path : Seq[Field], failFast : Boolean) : Seq[ValidationError] = {
|
||||
val _allValidationErrors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
// ================== `type` validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ================== requiredField validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ================== stringField validation ==================
|
||||
// validate min length 5
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
val len = if stringField == null then 0 else stringField.length
|
||||
if (len < 5) {
|
||||
_allValidationErrors += ValidationError(path :+ ComplexRequest.Fields.stringField, s"length $len is shorter than the min length 5")
|
||||
}
|
||||
}
|
||||
// validate max length 100
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
val len = if stringField == null then 0 else stringField.length
|
||||
if (len < 100) {
|
||||
_allValidationErrors += ValidationError(path :+ ComplexRequest.Fields.stringField, s"length $len is longer than the max length 100")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ================== integerField validation ==================
|
||||
// validate against minimum 1
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
if !(integerField >= 1) then
|
||||
_allValidationErrors += ValidationError(path :+ ComplexRequest.Fields.integerField, s"value '$integerField' is not greater than the minimum value 1")
|
||||
}
|
||||
// validate against maximum 100
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
if !(integerField <= 100) then
|
||||
_allValidationErrors += ValidationError(path :+ ComplexRequest.Fields.integerField, s"value '$integerField' is not greater than the maximum value 100")
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ================== numberField validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ================== booleanField validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ================== emailField validation ==================
|
||||
// validate emailField is a valid email address
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
val emailRegex = """^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"""
|
||||
// validate emailField is email
|
||||
if (emailField == null || !emailRegex.r.matches(emailField)) {
|
||||
_allValidationErrors += ValidationError(path :+ ComplexRequest.Fields.emailField, s"$emailField is not a valid email address according to the pattern $emailRegex")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ================== uuidField validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ================== dateField validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ================== dateTimeField validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ================== arrayField validation ==================
|
||||
|
||||
// validate min items 1
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
val len = if arrayField == null then 0 else arrayField.size
|
||||
if (len < 1) {
|
||||
_allValidationErrors += ValidationError(path :+ ComplexRequest.Fields.arrayField, s"arrayField has $len, which is less than the min items 1")
|
||||
}
|
||||
}
|
||||
// validate min items 10
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
val len = if arrayField == null then 0 else arrayField.size
|
||||
if (len > 10) {
|
||||
_allValidationErrors += ValidationError(path :+ ComplexRequest.Fields.arrayField, s"arrayField has $len, which is greater than the max items 10")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ================== enumField validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ================== nestedObject validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
// validating nestedObject
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
if nestedObject != null then _allValidationErrors ++= nestedObject.validationErrors(path :+ ComplexRequest.Fields.nestedObject, failFast)
|
||||
}
|
||||
|
||||
// ================== arrayOfObjectsField validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
if (arrayOfObjectsField != null) {
|
||||
arrayOfObjectsField.zipWithIndex.foreach {
|
||||
case (value, i) if _allValidationErrors.isEmpty || !failFast =>
|
||||
_allValidationErrors ++= value.validationErrors(
|
||||
path :+ ComplexRequest.Fields.arrayOfObjectsField :+ Field(i.toString),
|
||||
failFast)
|
||||
case (value, i) =>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ================== patternField validation ==================
|
||||
// validate against pattern '^[a-zA-Z0-9]{3,10}$'
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
val regex = """^[a-zA-Z0-9]{3,10}$"""
|
||||
if patternField == null || !regex.r.matches(patternField) then
|
||||
_allValidationErrors += ValidationError(path :+ ComplexRequest.Fields.patternField, s"value '$patternField' doesn't match pattern $regex")
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ================== nullableField validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
_allValidationErrors.toSeq
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the validated model within a Try (if successful)
|
||||
*/
|
||||
def validated(failFast : Boolean = false) : scala.util.Try[ComplexRequest] = {
|
||||
validationErrors(Vector(), failFast) match {
|
||||
case Seq() => Success(asModel)
|
||||
case first +: theRest => Failure(ValidationErrors(first, theRest))
|
||||
}
|
||||
}
|
||||
|
||||
/** use 'validated' to check validation */
|
||||
def asModel : ComplexRequest = {
|
||||
ComplexRequest(
|
||||
`type` = `type` /* 2 */,
|
||||
requiredField = requiredField /* 2 */,
|
||||
stringField = Option(stringField) /* 1 */,
|
||||
integerField = Option(integerField) /* 1 */,
|
||||
numberField = Option(numberField) /* 1 */,
|
||||
booleanField = Option(booleanField) /* 1 */,
|
||||
emailField = Option(emailField) /* 1 */,
|
||||
uuidField = Option(uuidField) /* 1 */,
|
||||
dateField = Option(dateField) /* 1 */,
|
||||
dateTimeField = Option(dateTimeField) /* 1 */,
|
||||
arrayField = arrayField /* 2 */,
|
||||
enumField = Option(enumField) /* 1 */,
|
||||
nestedObject = Option(nestedObject).map(_.asModel) /* 4 */,
|
||||
arrayOfObjectsField = arrayOfObjectsField.map(_.asModel) /* 5 */,
|
||||
patternField = Option(patternField) /* 1 */,
|
||||
nullableField = Option(nullableField) /* 1 */
|
||||
, additionalProperties
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object ComplexRequestData {
|
||||
|
||||
def validated(d8a : ComplexRequestData, failFast : Boolean) : scala.util.Try[ComplexRequest] = d8a.validated(failFast)
|
||||
|
||||
def fromJson(jason : ujson.Value) : ComplexRequestData = try {
|
||||
val data = read[ComplexRequestData](jason)
|
||||
val obj = jason.obj
|
||||
ComplexRequest.Fields.values.foreach(v => obj.value.subtractOne(v.fieldName))
|
||||
data.copy(additionalProperties = obj)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error creating ComplexRequestData from json '$jason': $e")
|
||||
}
|
||||
|
||||
def fromJsonString(jason : String) : ComplexRequestData = {
|
||||
val parsed = try {
|
||||
read[ujson.Value](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason': $e")
|
||||
}
|
||||
fromJson(parsed)
|
||||
}
|
||||
|
||||
def manyFromJsonString(jason : String) : Seq[ComplexRequestData] = try {
|
||||
read[List[ComplexRequestData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as list: $e")
|
||||
}
|
||||
|
||||
def manyFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Seq[ComplexRequest]] = {
|
||||
Try(manyFromJsonString(jason)).flatMap { list =>
|
||||
list.zipWithIndex.foldLeft(Try(Vector[ComplexRequest]())) {
|
||||
case (Success(list), (next, i)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(list :+ ok)
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $i: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def mapFromJsonString(jason : String) : Map[String, ComplexRequestData] = try {
|
||||
read[Map[String, ComplexRequestData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as map: $e")
|
||||
}
|
||||
|
||||
|
||||
def mapFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Map[String, ComplexRequest]] = {
|
||||
Try(mapFromJsonString(jason)).flatMap { map =>
|
||||
map.foldLeft(Try(Map[String, ComplexRequest]())) {
|
||||
case (Success(map), (key, next)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(map.updated(key, ok))
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $key: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using model.mustache
|
||||
package sample.cask.model
|
||||
|
||||
import scala.util.control.NonFatal
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
|
||||
case class ComplexRequestNestedObject(
|
||||
/* A field within a nested object */
|
||||
nestedField1: Option[String] = None ,
|
||||
/* Another field in a nested object */
|
||||
nestedField2: Option[Int] = None
|
||||
|
||||
|
||||
) {
|
||||
|
||||
def asJsonString: String = asData.asJsonString
|
||||
def asJson: ujson.Value = asData.asJson
|
||||
|
||||
def asData : ComplexRequestNestedObjectData = {
|
||||
ComplexRequestNestedObjectData(
|
||||
nestedField1 = nestedField1.getOrElse("") /* 1 */,
|
||||
nestedField2 = nestedField2.getOrElse(0) /* 1 */
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object ComplexRequestNestedObject {
|
||||
given RW[ComplexRequestNestedObject] = summon[RW[ujson.Value]].bimap[ComplexRequestNestedObject](_.asJson, json => read[ComplexRequestNestedObjectData](json).asModel)
|
||||
|
||||
enum Fields(val fieldName : String) extends Field(fieldName) {
|
||||
case nestedField1 extends Fields("nestedField1")
|
||||
case nestedField2 extends Fields("nestedField2")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,139 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelData.mustache
|
||||
package sample.cask.model
|
||||
import scala.util.control.NonFatal
|
||||
import scala.util.*
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
/** ComplexRequestNestedObjectData a data transfer object, primarily for simple json serialisation.
|
||||
* It has no validation - there may be nulls, values out of range, etc
|
||||
*/
|
||||
case class ComplexRequestNestedObjectData(
|
||||
/* A field within a nested object */
|
||||
nestedField1: String = "" ,
|
||||
/* Another field in a nested object */
|
||||
nestedField2: Int = 0
|
||||
|
||||
|
||||
) derives RW {
|
||||
|
||||
def asJsonString: String = asJson.toString()
|
||||
|
||||
def asJson : ujson.Value = {
|
||||
val jason = writeJs(this)
|
||||
jason
|
||||
}
|
||||
|
||||
def validationErrors(path : Seq[Field], failFast : Boolean) : Seq[ValidationError] = {
|
||||
val _allValidationErrors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
// ================== nestedField1 validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ================== nestedField2 validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
_allValidationErrors.toSeq
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the validated model within a Try (if successful)
|
||||
*/
|
||||
def validated(failFast : Boolean = false) : scala.util.Try[ComplexRequestNestedObject] = {
|
||||
validationErrors(Vector(), failFast) match {
|
||||
case Seq() => Success(asModel)
|
||||
case first +: theRest => Failure(ValidationErrors(first, theRest))
|
||||
}
|
||||
}
|
||||
|
||||
/** use 'validated' to check validation */
|
||||
def asModel : ComplexRequestNestedObject = {
|
||||
ComplexRequestNestedObject(
|
||||
nestedField1 = Option(nestedField1) /* 1 */,
|
||||
nestedField2 = Option(nestedField2) /* 1 */
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object ComplexRequestNestedObjectData {
|
||||
|
||||
def validated(d8a : ComplexRequestNestedObjectData, failFast : Boolean) : scala.util.Try[ComplexRequestNestedObject] = d8a.validated(failFast)
|
||||
|
||||
def fromJson(jason : ujson.Value) : ComplexRequestNestedObjectData = try {
|
||||
val data = read[ComplexRequestNestedObjectData](jason)
|
||||
data
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error creating ComplexRequestNestedObjectData from json '$jason': $e")
|
||||
}
|
||||
|
||||
def fromJsonString(jason : String) : ComplexRequestNestedObjectData = {
|
||||
val parsed = try {
|
||||
read[ujson.Value](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason': $e")
|
||||
}
|
||||
fromJson(parsed)
|
||||
}
|
||||
|
||||
def manyFromJsonString(jason : String) : Seq[ComplexRequestNestedObjectData] = try {
|
||||
read[List[ComplexRequestNestedObjectData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as list: $e")
|
||||
}
|
||||
|
||||
def manyFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Seq[ComplexRequestNestedObject]] = {
|
||||
Try(manyFromJsonString(jason)).flatMap { list =>
|
||||
list.zipWithIndex.foldLeft(Try(Vector[ComplexRequestNestedObject]())) {
|
||||
case (Success(list), (next, i)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(list :+ ok)
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $i: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def mapFromJsonString(jason : String) : Map[String, ComplexRequestNestedObjectData] = try {
|
||||
read[Map[String, ComplexRequestNestedObjectData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as map: $e")
|
||||
}
|
||||
|
||||
|
||||
def mapFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Map[String, ComplexRequestNestedObject]] = {
|
||||
Try(mapFromJsonString(jason)).flatMap { map =>
|
||||
map.foldLeft(Try(Map[String, ComplexRequestNestedObject]())) {
|
||||
case (Success(map), (key, next)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(map.updated(key, ok))
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $key: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using model.mustache
|
||||
package sample.cask.model
|
||||
import java.time.OffsetDateTime
|
||||
|
||||
import scala.util.control.NonFatal
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
|
||||
type OneOfRequestAndResponse200Response = SomeResponse1 | SomeResponse2
|
||||
object OneOfRequestAndResponse200Response {
|
||||
|
||||
given RW[OneOfRequestAndResponse200Response] = RW.merge(summon[RW[SomeResponse1]], summon[RW[SomeResponse2]])
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelData.mustache
|
||||
package sample.cask.model
|
||||
import java.time.OffsetDateTime
|
||||
import scala.util.control.NonFatal
|
||||
import scala.util.*
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
type OneOfRequestAndResponse200ResponseData = SomeResponse1Data | SomeResponse2Data
|
||||
|
||||
object OneOfRequestAndResponse200ResponseData {
|
||||
|
||||
def validated(d8a : OneOfRequestAndResponse200ResponseData, failFast: Boolean) : Try[OneOfRequestAndResponse200Response] = {
|
||||
d8a match {
|
||||
case value : SomeResponse1Data => value.validated(failFast)
|
||||
case value : SomeResponse2Data => value.validated(failFast)
|
||||
}
|
||||
}
|
||||
|
||||
def fromJsonString(jason : String) = fromJson {
|
||||
try {
|
||||
read[ujson.Value](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason': $e")
|
||||
}
|
||||
}
|
||||
|
||||
def fromJson(jason : ujson.Value) : OneOfRequestAndResponse200ResponseData = {
|
||||
val attempt = Try(SomeResponse1Data.fromJson(jason)) .orElse( Try(SomeResponse2Data.fromJson(jason)) ) /* not first */
|
||||
attempt.get
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using model.mustache
|
||||
package sample.cask.model
|
||||
import java.time.LocalDate
|
||||
import java.time.OffsetDateTime
|
||||
import java.util.UUID
|
||||
import scala.math.BigDecimal
|
||||
|
||||
import scala.util.control.NonFatal
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
|
||||
type OneOfRequestAndResponseRequest = AllOfRequest | ComplexRequest
|
||||
object OneOfRequestAndResponseRequest {
|
||||
|
||||
given RW[OneOfRequestAndResponseRequest] = RW.merge(summon[RW[AllOfRequest]], summon[RW[ComplexRequest]])
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelData.mustache
|
||||
package sample.cask.model
|
||||
import java.time.LocalDate
|
||||
import java.time.OffsetDateTime
|
||||
import java.util.UUID
|
||||
import scala.math.BigDecimal
|
||||
import scala.util.control.NonFatal
|
||||
import scala.util.*
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
type OneOfRequestAndResponseRequestData = AllOfRequestData | ComplexRequestData
|
||||
|
||||
object OneOfRequestAndResponseRequestData {
|
||||
|
||||
def validated(d8a : OneOfRequestAndResponseRequestData, failFast: Boolean) : Try[OneOfRequestAndResponseRequest] = {
|
||||
d8a match {
|
||||
case value : AllOfRequestData => value.validated(failFast)
|
||||
case value : ComplexRequestData => value.validated(failFast)
|
||||
}
|
||||
}
|
||||
|
||||
def fromJsonString(jason : String) = fromJson {
|
||||
try {
|
||||
read[ujson.Value](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason': $e")
|
||||
}
|
||||
}
|
||||
|
||||
def fromJson(jason : ujson.Value) : OneOfRequestAndResponseRequestData = {
|
||||
val attempt = Try(AllOfRequestData.fromJson(jason)) .orElse( Try(ComplexRequestData.fromJson(jason)) ) /* not first */
|
||||
attempt.get
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@ import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
|
||||
|
||||
case class Order(
|
||||
id: Option[Long] = None ,
|
||||
petId: Option[Long] = None ,
|
||||
@ -73,3 +73,4 @@ enum Fields(val fieldName : String) extends Field(fieldName) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -45,7 +45,7 @@ case class OrderData(
|
||||
}
|
||||
|
||||
def validationErrors(path : Seq[Field], failFast : Boolean) : Seq[ValidationError] = {
|
||||
val errors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
val _allValidationErrors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
// ================== id validation ==================
|
||||
|
||||
|
||||
@ -82,7 +82,7 @@ case class OrderData(
|
||||
|
||||
|
||||
|
||||
errors.toSeq
|
||||
_allValidationErrors.toSeq
|
||||
}
|
||||
|
||||
/**
|
||||
@ -111,6 +111,8 @@ case class OrderData(
|
||||
|
||||
object OrderData {
|
||||
|
||||
def validated(d8a : OrderData, failFast : Boolean) : scala.util.Try[Order] = d8a.validated(failFast)
|
||||
|
||||
def fromJson(jason : ujson.Value) : OrderData = try {
|
||||
val data = read[OrderData](jason)
|
||||
data
|
||||
|
@ -21,7 +21,7 @@ import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
|
||||
|
||||
case class Pet(
|
||||
id: Option[Long] = None ,
|
||||
category: Option[Category] = None ,
|
||||
@ -72,3 +72,4 @@ enum Fields(val fieldName : String) extends Field(fieldName) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -44,7 +44,7 @@ case class PetData(
|
||||
}
|
||||
|
||||
def validationErrors(path : Seq[Field], failFast : Boolean) : Seq[ValidationError] = {
|
||||
val errors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
val _allValidationErrors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
// ================== id validation ==================
|
||||
|
||||
|
||||
@ -57,8 +57,8 @@ case class PetData(
|
||||
|
||||
|
||||
// validating category
|
||||
if (errors.isEmpty || !failFast) {
|
||||
if category != null then errors ++= category.validationErrors(path :+ Pet.Fields.category, failFast)
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
if category != null then _allValidationErrors ++= category.validationErrors(path :+ Pet.Fields.category, failFast)
|
||||
}
|
||||
|
||||
// ================== name validation ==================
|
||||
@ -78,11 +78,11 @@ case class PetData(
|
||||
|
||||
|
||||
|
||||
if (errors.isEmpty || !failFast) {
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
if (tags != null) {
|
||||
tags.zipWithIndex.foreach {
|
||||
case (value, i) if errors.isEmpty || !failFast =>
|
||||
errors ++= value.validationErrors(
|
||||
case (value, i) if _allValidationErrors.isEmpty || !failFast =>
|
||||
_allValidationErrors ++= value.validationErrors(
|
||||
path :+ Pet.Fields.tags :+ Field(i.toString),
|
||||
failFast)
|
||||
case (value, i) =>
|
||||
@ -97,7 +97,7 @@ case class PetData(
|
||||
|
||||
|
||||
|
||||
errors.toSeq
|
||||
_allValidationErrors.toSeq
|
||||
}
|
||||
|
||||
/**
|
||||
@ -126,6 +126,8 @@ case class PetData(
|
||||
|
||||
object PetData {
|
||||
|
||||
def validated(d8a : PetData, failFast : Boolean) : scala.util.Try[Pet] = d8a.validated(failFast)
|
||||
|
||||
def fromJson(jason : ujson.Value) : PetData = try {
|
||||
val data = read[PetData](jason)
|
||||
data
|
||||
|
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using model.mustache
|
||||
package sample.cask.model
|
||||
|
||||
import scala.util.control.NonFatal
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
|
||||
case class SomeResponse1(
|
||||
status: String,
|
||||
message: String
|
||||
|
||||
|
||||
) {
|
||||
|
||||
def asJsonString: String = asData.asJsonString
|
||||
def asJson: ujson.Value = asData.asJson
|
||||
|
||||
def asData : SomeResponse1Data = {
|
||||
SomeResponse1Data(
|
||||
status = status /* 2 */,
|
||||
message = message /* 2 */
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object SomeResponse1 {
|
||||
given RW[SomeResponse1] = summon[RW[ujson.Value]].bimap[SomeResponse1](_.asJson, json => read[SomeResponse1Data](json).asModel)
|
||||
|
||||
enum Fields(val fieldName : String) extends Field(fieldName) {
|
||||
case status extends Fields("status")
|
||||
case message extends Fields("message")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,137 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelData.mustache
|
||||
package sample.cask.model
|
||||
import scala.util.control.NonFatal
|
||||
import scala.util.*
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
/** SomeResponse1Data a data transfer object, primarily for simple json serialisation.
|
||||
* It has no validation - there may be nulls, values out of range, etc
|
||||
*/
|
||||
case class SomeResponse1Data(
|
||||
status: String,
|
||||
message: String
|
||||
|
||||
|
||||
) derives RW {
|
||||
|
||||
def asJsonString: String = asJson.toString()
|
||||
|
||||
def asJson : ujson.Value = {
|
||||
val jason = writeJs(this)
|
||||
jason
|
||||
}
|
||||
|
||||
def validationErrors(path : Seq[Field], failFast : Boolean) : Seq[ValidationError] = {
|
||||
val _allValidationErrors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
// ================== status validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ================== message validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
_allValidationErrors.toSeq
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the validated model within a Try (if successful)
|
||||
*/
|
||||
def validated(failFast : Boolean = false) : scala.util.Try[SomeResponse1] = {
|
||||
validationErrors(Vector(), failFast) match {
|
||||
case Seq() => Success(asModel)
|
||||
case first +: theRest => Failure(ValidationErrors(first, theRest))
|
||||
}
|
||||
}
|
||||
|
||||
/** use 'validated' to check validation */
|
||||
def asModel : SomeResponse1 = {
|
||||
SomeResponse1(
|
||||
status = status /* 2 */,
|
||||
message = message /* 2 */
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object SomeResponse1Data {
|
||||
|
||||
def validated(d8a : SomeResponse1Data, failFast : Boolean) : scala.util.Try[SomeResponse1] = d8a.validated(failFast)
|
||||
|
||||
def fromJson(jason : ujson.Value) : SomeResponse1Data = try {
|
||||
val data = read[SomeResponse1Data](jason)
|
||||
data
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error creating SomeResponse1Data from json '$jason': $e")
|
||||
}
|
||||
|
||||
def fromJsonString(jason : String) : SomeResponse1Data = {
|
||||
val parsed = try {
|
||||
read[ujson.Value](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason': $e")
|
||||
}
|
||||
fromJson(parsed)
|
||||
}
|
||||
|
||||
def manyFromJsonString(jason : String) : Seq[SomeResponse1Data] = try {
|
||||
read[List[SomeResponse1Data]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as list: $e")
|
||||
}
|
||||
|
||||
def manyFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Seq[SomeResponse1]] = {
|
||||
Try(manyFromJsonString(jason)).flatMap { list =>
|
||||
list.zipWithIndex.foldLeft(Try(Vector[SomeResponse1]())) {
|
||||
case (Success(list), (next, i)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(list :+ ok)
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $i: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def mapFromJsonString(jason : String) : Map[String, SomeResponse1Data] = try {
|
||||
read[Map[String, SomeResponse1Data]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as map: $e")
|
||||
}
|
||||
|
||||
|
||||
def mapFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Map[String, SomeResponse1]] = {
|
||||
Try(mapFromJsonString(jason)).flatMap { map =>
|
||||
map.foldLeft(Try(Map[String, SomeResponse1]())) {
|
||||
case (Success(map), (key, next)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(map.updated(key, ok))
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $key: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using model.mustache
|
||||
package sample.cask.model
|
||||
import java.time.OffsetDateTime
|
||||
|
||||
import scala.util.control.NonFatal
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
|
||||
case class SomeResponse2(
|
||||
id: String,
|
||||
createdAt: OffsetDateTime,
|
||||
details: Option[SomeResponse2Details] = None
|
||||
|
||||
|
||||
) {
|
||||
|
||||
def asJsonString: String = asData.asJsonString
|
||||
def asJson: ujson.Value = asData.asJson
|
||||
|
||||
def asData : SomeResponse2Data = {
|
||||
SomeResponse2Data(
|
||||
id = id /* 2 */,
|
||||
createdAt = createdAt /* 2 */,
|
||||
details = details.map(_.asData).getOrElse(null) /* 4 */
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object SomeResponse2 {
|
||||
given RW[SomeResponse2] = summon[RW[ujson.Value]].bimap[SomeResponse2](_.asJson, json => read[SomeResponse2Data](json).asModel)
|
||||
|
||||
enum Fields(val fieldName : String) extends Field(fieldName) {
|
||||
case id extends Fields("id")
|
||||
case createdAt extends Fields("createdAt")
|
||||
case details extends Fields("details")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,156 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelData.mustache
|
||||
package sample.cask.model
|
||||
import java.time.OffsetDateTime
|
||||
import scala.util.control.NonFatal
|
||||
import scala.util.*
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
/** SomeResponse2Data a data transfer object, primarily for simple json serialisation.
|
||||
* It has no validation - there may be nulls, values out of range, etc
|
||||
*/
|
||||
case class SomeResponse2Data(
|
||||
id: String,
|
||||
createdAt: OffsetDateTime,
|
||||
details: SomeResponse2DetailsData = null
|
||||
|
||||
|
||||
) derives RW {
|
||||
|
||||
def asJsonString: String = asJson.toString()
|
||||
|
||||
def asJson : ujson.Value = {
|
||||
val jason = writeJs(this)
|
||||
jason
|
||||
}
|
||||
|
||||
def validationErrors(path : Seq[Field], failFast : Boolean) : Seq[ValidationError] = {
|
||||
val _allValidationErrors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
// ================== id validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ================== createdAt validation ==================
|
||||
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
if (createdAt == null) {
|
||||
_allValidationErrors += ValidationError(path :+ SomeResponse2.Fields.createdAt, "createdAt is a required field and cannot be null")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ================== details validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
// validating details
|
||||
if (_allValidationErrors.isEmpty || !failFast) {
|
||||
if details != null then _allValidationErrors ++= details.validationErrors(path :+ SomeResponse2.Fields.details, failFast)
|
||||
}
|
||||
|
||||
_allValidationErrors.toSeq
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the validated model within a Try (if successful)
|
||||
*/
|
||||
def validated(failFast : Boolean = false) : scala.util.Try[SomeResponse2] = {
|
||||
validationErrors(Vector(), failFast) match {
|
||||
case Seq() => Success(asModel)
|
||||
case first +: theRest => Failure(ValidationErrors(first, theRest))
|
||||
}
|
||||
}
|
||||
|
||||
/** use 'validated' to check validation */
|
||||
def asModel : SomeResponse2 = {
|
||||
SomeResponse2(
|
||||
id = id /* 2 */,
|
||||
createdAt = createdAt /* 2 */,
|
||||
details = Option(details).map(_.asModel) /* 4 */
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object SomeResponse2Data {
|
||||
|
||||
def validated(d8a : SomeResponse2Data, failFast : Boolean) : scala.util.Try[SomeResponse2] = d8a.validated(failFast)
|
||||
|
||||
def fromJson(jason : ujson.Value) : SomeResponse2Data = try {
|
||||
val data = read[SomeResponse2Data](jason)
|
||||
data
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error creating SomeResponse2Data from json '$jason': $e")
|
||||
}
|
||||
|
||||
def fromJsonString(jason : String) : SomeResponse2Data = {
|
||||
val parsed = try {
|
||||
read[ujson.Value](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason': $e")
|
||||
}
|
||||
fromJson(parsed)
|
||||
}
|
||||
|
||||
def manyFromJsonString(jason : String) : Seq[SomeResponse2Data] = try {
|
||||
read[List[SomeResponse2Data]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as list: $e")
|
||||
}
|
||||
|
||||
def manyFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Seq[SomeResponse2]] = {
|
||||
Try(manyFromJsonString(jason)).flatMap { list =>
|
||||
list.zipWithIndex.foldLeft(Try(Vector[SomeResponse2]())) {
|
||||
case (Success(list), (next, i)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(list :+ ok)
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $i: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def mapFromJsonString(jason : String) : Map[String, SomeResponse2Data] = try {
|
||||
read[Map[String, SomeResponse2Data]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as map: $e")
|
||||
}
|
||||
|
||||
|
||||
def mapFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Map[String, SomeResponse2]] = {
|
||||
Try(mapFromJsonString(jason)).flatMap { map =>
|
||||
map.foldLeft(Try(Map[String, SomeResponse2]())) {
|
||||
case (Success(map), (key, next)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(map.updated(key, ok))
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $key: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using model.mustache
|
||||
package sample.cask.model
|
||||
|
||||
import scala.util.control.NonFatal
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
|
||||
case class SomeResponse2Details(
|
||||
description: Option[String] = None ,
|
||||
status: Option[String] = None
|
||||
|
||||
|
||||
) {
|
||||
|
||||
def asJsonString: String = asData.asJsonString
|
||||
def asJson: ujson.Value = asData.asJson
|
||||
|
||||
def asData : SomeResponse2DetailsData = {
|
||||
SomeResponse2DetailsData(
|
||||
description = description.getOrElse("") /* 1 */,
|
||||
status = status.getOrElse("") /* 1 */
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object SomeResponse2Details {
|
||||
given RW[SomeResponse2Details] = summon[RW[ujson.Value]].bimap[SomeResponse2Details](_.asJson, json => read[SomeResponse2DetailsData](json).asModel)
|
||||
|
||||
enum Fields(val fieldName : String) extends Field(fieldName) {
|
||||
case description extends Fields("description")
|
||||
case status extends Fields("status")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,137 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelData.mustache
|
||||
package sample.cask.model
|
||||
import scala.util.control.NonFatal
|
||||
import scala.util.*
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
/** SomeResponse2DetailsData a data transfer object, primarily for simple json serialisation.
|
||||
* It has no validation - there may be nulls, values out of range, etc
|
||||
*/
|
||||
case class SomeResponse2DetailsData(
|
||||
description: String = "" ,
|
||||
status: String = ""
|
||||
|
||||
|
||||
) derives RW {
|
||||
|
||||
def asJsonString: String = asJson.toString()
|
||||
|
||||
def asJson : ujson.Value = {
|
||||
val jason = writeJs(this)
|
||||
jason
|
||||
}
|
||||
|
||||
def validationErrors(path : Seq[Field], failFast : Boolean) : Seq[ValidationError] = {
|
||||
val _allValidationErrors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
// ================== description validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ================== status validation ==================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
_allValidationErrors.toSeq
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the validated model within a Try (if successful)
|
||||
*/
|
||||
def validated(failFast : Boolean = false) : scala.util.Try[SomeResponse2Details] = {
|
||||
validationErrors(Vector(), failFast) match {
|
||||
case Seq() => Success(asModel)
|
||||
case first +: theRest => Failure(ValidationErrors(first, theRest))
|
||||
}
|
||||
}
|
||||
|
||||
/** use 'validated' to check validation */
|
||||
def asModel : SomeResponse2Details = {
|
||||
SomeResponse2Details(
|
||||
description = Option(description) /* 1 */,
|
||||
status = Option(status) /* 1 */
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object SomeResponse2DetailsData {
|
||||
|
||||
def validated(d8a : SomeResponse2DetailsData, failFast : Boolean) : scala.util.Try[SomeResponse2Details] = d8a.validated(failFast)
|
||||
|
||||
def fromJson(jason : ujson.Value) : SomeResponse2DetailsData = try {
|
||||
val data = read[SomeResponse2DetailsData](jason)
|
||||
data
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error creating SomeResponse2DetailsData from json '$jason': $e")
|
||||
}
|
||||
|
||||
def fromJsonString(jason : String) : SomeResponse2DetailsData = {
|
||||
val parsed = try {
|
||||
read[ujson.Value](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason': $e")
|
||||
}
|
||||
fromJson(parsed)
|
||||
}
|
||||
|
||||
def manyFromJsonString(jason : String) : Seq[SomeResponse2DetailsData] = try {
|
||||
read[List[SomeResponse2DetailsData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as list: $e")
|
||||
}
|
||||
|
||||
def manyFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Seq[SomeResponse2Details]] = {
|
||||
Try(manyFromJsonString(jason)).flatMap { list =>
|
||||
list.zipWithIndex.foldLeft(Try(Vector[SomeResponse2Details]())) {
|
||||
case (Success(list), (next, i)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(list :+ ok)
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $i: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def mapFromJsonString(jason : String) : Map[String, SomeResponse2DetailsData] = try {
|
||||
read[Map[String, SomeResponse2DetailsData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as map: $e")
|
||||
}
|
||||
|
||||
|
||||
def mapFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Map[String, SomeResponse2Details]] = {
|
||||
Try(mapFromJsonString(jason)).flatMap { map =>
|
||||
map.foldLeft(Try(Map[String, SomeResponse2Details]())) {
|
||||
case (Success(map), (key, next)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(map.updated(key, ok))
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $key: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
|
||||
|
||||
case class Tag(
|
||||
id: Option[Long] = None ,
|
||||
name: Option[String] = None
|
||||
@ -52,3 +52,4 @@ enum Fields(val fieldName : String) extends Field(fieldName) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -39,7 +39,7 @@ case class TagData(
|
||||
}
|
||||
|
||||
def validationErrors(path : Seq[Field], failFast : Boolean) : Seq[ValidationError] = {
|
||||
val errors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
val _allValidationErrors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
// ================== id validation ==================
|
||||
|
||||
|
||||
@ -52,7 +52,7 @@ case class TagData(
|
||||
|
||||
|
||||
|
||||
errors.toSeq
|
||||
_allValidationErrors.toSeq
|
||||
}
|
||||
|
||||
/**
|
||||
@ -77,6 +77,8 @@ case class TagData(
|
||||
|
||||
object TagData {
|
||||
|
||||
def validated(d8a : TagData, failFast : Boolean) : scala.util.Try[Tag] = d8a.validated(failFast)
|
||||
|
||||
def fromJson(jason : ujson.Value) : TagData = try {
|
||||
val data = read[TagData](jason)
|
||||
data
|
||||
|
@ -21,7 +21,7 @@ import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
|
||||
|
||||
|
||||
case class User(
|
||||
id: Option[Long] = None ,
|
||||
username: Option[String] = None ,
|
||||
@ -71,3 +71,4 @@ enum Fields(val fieldName : String) extends Field(fieldName) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -46,7 +46,7 @@ case class UserData(
|
||||
}
|
||||
|
||||
def validationErrors(path : Seq[Field], failFast : Boolean) : Seq[ValidationError] = {
|
||||
val errors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
val _allValidationErrors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
// ================== id validation ==================
|
||||
|
||||
|
||||
@ -95,7 +95,7 @@ case class UserData(
|
||||
|
||||
|
||||
|
||||
errors.toSeq
|
||||
_allValidationErrors.toSeq
|
||||
}
|
||||
|
||||
/**
|
||||
@ -126,6 +126,8 @@ case class UserData(
|
||||
|
||||
object UserData {
|
||||
|
||||
def validated(d8a : UserData, failFast : Boolean) : scala.util.Try[User] = d8a.validated(failFast)
|
||||
|
||||
def fromJson(jason : ujson.Value) : UserData = try {
|
||||
val data = read[UserData](jason)
|
||||
data
|
||||
|
Loading…
x
Reference in New Issue
Block a user