A no-surprise Java model of the Swagger 2.0 specification.
Fanfaron allows developers to work with Swagger 2.0 definitions using Java. It is an alternative to the swagger-model module of the swagger-core project. The main advantage over swagger-module is that it is better aligned with the specification: the model is simpler and matches the specification more closely. This enables Fanfaron to better support Swagger features, like global security requirements, which are impossible to extract today using swagger-model 1.5.3.
Fanfaron requires Java 7 or later. Be advised that moving to Java 8 is being considered, although model classes will preferably stay clear of any Java 8 features, so that they remain extractable for use in lower versions.
<dependency>
<groupId>com.github.hgwood.fanfaron</groupId>
<artifactId>fanfaron</artifactId>
<version>8.0.0</version>
</dependency>
group: 'com.github.hgwood.fanfaron', name: 'fanfaron', version: '8.0.0'
mvn install
Use Jackson Databind's ObjectMapper to read the serialized Swagger
into Fanfaron's Swagger class.
try (InputStream swaggerStream = getClass().getResourceAsStream("swagger.json")) {
return new ObjectMapper().readValue(swaggerStream, Swagger.class);
}What's wrong with Swagger Core?
- It lags behind the spec, and the team is reluctant to catch up when it would incur breaking changes.
- The model is polluted because it wants to do everything: ensure backward-compatibility with getters and setters, provide a builder interface, provide specific shortcut methods to handle collections. This means that there is a lot of legacy code to maintain, and that the model is more complicated than required.
Fanfaron is able to deserialize all fields of all objects defined in the Swagger 2.0 specification, without known limitation. Please open an issue if you detect any.
Furthermore, there is no kind of validation whatsoever, aside from very basic type correctness (see Type mapping). For
example, while the specification says the value of the root swagger field "MUST be "2.0"", Fanfaron makes no such
verification.
- Structural equality: if all fields of 2 objects are equal, then these 2 objects are equal.
- Traversal with user-defined side-effects (SAX-style).
new SideEffectingDepthFirstVisit(new SimpleVisitor() {
public void visit(PathItem pathItem, String path) {
// this method will be called for all path items defined in the swagger definition
}
public void visit(Operation operation) {
// same for operations
}
public void visit(Schema schema, String name) {
// this method will be called for all named schemas defined in the swagger definition
// use #visit(Schema) for unnamed schemas
}
}).run(swagger);- Value defaulting: all default values defined by the spec can be set on any model object. Can be combined with a traversal to set all defaults in a definition.
// on a single object
Operation operation = new Operation();
new DefaultFiller().vist(operation);
assertEquals(false, operation.deprecated);
// on a definition
Operation operation = new Operation();
PathItem pathItem = new PathItem();
pathItem.get = operation;
Paths paths = new Paths();
paths.put("/path", pathItem);
Swagger swagger = new Swagger();
swagger.paths = paths;
new SideEffectingDepthFirstVisit(new DefaultFiller()).run(swagger);
assertEquals(false, operation.deprecated);The objects defined by the spec are modeled in the simplest way possible, which is as Java classes with public fields
and equals and hashCode implementations that use all fields.
The types of the fields match the types defined in the spec with the following mapping:
| Type in spec | Type in Fanfaron |
|---|---|
| string | String |
| integer | BigInteger |
| number | BigDecimal |
| boolean | Boolean |
- | Object T | T [T] | List<T> T | Reference Object | TOrReference
Furthermore, objects with dynamically-named fields of type T are mapped using classes that implement Map<String, T>.
Only one class has a non-obvious mapping: AdditionalProperties (the type of the additionalProperties field in the
Schema Object). This is because this field can contain either a boolean value or a Schema Object, and that is not
representable in Java. Therefore, AdditionalProperties has 2 fields, one for each possibility: allowed for the
boolean, and schema for the Schema Object.
The classes directly mapping the spec are only meant to do just that, and nothing else. They will never have accessors or any kind of validation. Those belong in adapters and validators, which may be added into this library in the future.
- Validation
- An easier way to build a model from Java
- An easier way to work with the model, either through utility functions that manipulate the JSON model, or a
higher-level model with proper Java types and useful methods.
- Optional and empty collections instead of null
- Value to key references for objects with patterned fields (operation to HTTP method, response to status code, ...)
- Dereferencing
- Traversal
- Collecting all entities of the same type (all parameters, all responses, ...)
- Types guarantee valid entities
- Other things?
The versioning follows semantic versioning.
- breaking feat: added support for
Schema.itemsbeing both aSchemaand a list ofSchemas- This is a breaking change because it adds a method to the
Visitorinterface. If you are depending onSimpleVisitorthen you should not be affected.
- This is a breaking change because it adds a method to the
- feat: added traversal with user-defined side-effects
- See Other Features
- breaking refactor: rewritten value defaulting to leverage traversal
DefaultFillerno longer descend in child objects on its own, but can be combined withSideEffectingDepthFirstVisitto achieve that.DefaultFillerno longer returns new objects but mutates its parameters instead.
- breaking refactor: moved vendor extensions utils to package utils.vendorextensions
- breaking refactor: removed json schema model
- breaking refactor: renamed root package to align with group id
- fix: recursive defaulting vastly improved
- It no longer chokes on
nulls while traversing the object tree. - It no longer cuts out part of the object tree.
- It no longer chokes on
Edit: it still won't copy over most properties. See #2. Fixed in 7.0.0 where it now mutates its parameters.
- feat: added vendor extensions support
- fix: added
hashCodetoDynamicObject
- chore: migrated build to Maven
- feat: recursive value defaulting
- Any model object can be traversed to set all default values defined by the spec.
Edit: it was found later that this new feature was incomplete and buggy due to insufficient testing. It was improved in 6.3.1.
- breaking refactor: type mapping changed for
T | Reference Object- Previously, all types that could be unioned with a Reference Object had a
$reffield. However those types are also used standalone in the specification. To bring the type mapping closer to the specification, these types no longer have a$reffield. Impacted types areParameterandResponse. To deal with the union case, companion types were added and named using the patternTOrReference:ParameterOrReferenceandResponseOrReference. These two types extends their respective standalone type, and add a$reffield. It now as easy to distinguish places where references are accepted and those where they are not as it is in the specification.
- Previously, all types that could be unioned with a Reference Object had a
- fix: missing
$refinResponse - refactor: replaced Guava's
ForwardingMapby own class- Guava is no longer a dependency.
- breaking feat: removed all default values
exclusiveMaximumandexclusiveMinimuminHeaderno longer default tofalse.exclusiveMaximumandexclusiveMinimuminItemsno longer default tofalse.deprecatedinOperationno longer defaults tofalse.requiredinParameteris now of typeBooleaninstead ofboolean.exclusiveMaximumandexclusiveMinimuminParameterno longer default tofalse.wrappedinXmlno longer defaults tofalse.
- breaking refactor:
Schemafor Swagger 2 made distinct fromSchemafor JSON Schema Draft 4- All classes defined from objects found in the Swagger 2.0 specification are now found in the package
fr.hgwood.fanfaron. Classes infr.hgwood.fanfaron.jsonschemaare not used to deserialize Swagger definitions. - The new
Schemaexactly matches the Schema Object defined by the Swagger 2.0 specification. Xmlwas moved tofr.hgwood.fanfaron, as it is specific to Swagger 2.0.PropertiesandAdditionalPropertieswere added tofr.hgwood.fanfaron. Those are not explicitly defined by the Swagger 2.0 specification, only implicitly.- Fields
xmlandexample, which are specific to Swagger 2.0, were removed fromfr.hgwood.fanfaron.jsonschema.Schema - Classes in
fr.hgwood.fanfaron.jsonschemacan still be used to deserialize the JSON schema subset defined by the Swagger 2.0 JSON schema, although that is no longer documented. Those classes might be moved to another library.
- All classes defined from objects found in the Swagger 2.0 specification are now found in the package
- feat: all fields for
Xml
- feat: support for all fields of all objects defined in the Swagger 2.0 specification except for
SchemaandXml
Edit: it was found later that the
$reffield was missing fromResponse. This is fixed in 5.0.1.
Edit: it was found later that the
itemsfield from the spec's Schema object supports both a schema and an array of schemas. Fanfaron 3.1.0 only supports the first case.
- fix: structural equality broken for
Schema
- breaking feat: can deserialize the Swagger 2 JSON schema
AdditionalPropertiesclass was removed.Schema.additionalPropertiesis now of typeBooleanOrSchemainstead ofAdditionalProperties.Itemsclass was removed.Schema.itemsis now of typeSchemainstead ofItems.
- breaking feat: support for allowed and forbidden additional properties in a schema
Schema.additionalPropertiesis now of typeAdditionalPropertiesinstead ofSchema.
- feat: structural equality
- feat: can deserialize pet store