From 2736b8cf30a1add054bed51588b092fdd8f75c9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20P?= Date: Thu, 2 Mar 2017 10:46:48 +0100 Subject: [PATCH] Add option to specify custom fragment separator characters (#697) * Add option to specify separator characters to be used to split non standard JSON Pointers * Fixes from review --- .../ant/Jsonschema2PojoTask.java | 16 ++++++++ .../src/site/Jsonschema2PojoTask.html | 7 ++++ .../org/jsonschema2pojo/cli/Arguments.java | 8 ++++ .../DefaultGenerationConfig.java | 8 ++++ .../org/jsonschema2pojo/FragmentResolver.java | 4 +- .../org/jsonschema2pojo/GenerationConfig.java | 8 ++++ .../java/org/jsonschema2pojo/SchemaStore.java | 14 ++++--- .../org/jsonschema2pojo/rules/ObjectRule.java | 4 +- .../jsonschema2pojo/rules/PropertyRule.java | 2 +- .../org/jsonschema2pojo/rules/SchemaRule.java | 2 +- .../jsonschema2pojo/FragmentResolverTest.java | 36 +++++++++--------- .../org/jsonschema2pojo/SchemaStoreTest.java | 26 ++++++------- .../jsonschema2pojo/rules/SchemaRuleTest.java | 11 +++++- .../gradle/JsonSchemaExtension.groovy | 5 ++- .../config/RefFragmentPathDelimitersIT.java | 37 +++++++++++++++++++ .../schema/properties/nonStandardRef.json | 19 ++++++++++ .../maven/Jsonschema2PojoMojo.java | 14 +++++++ 17 files changed, 177 insertions(+), 44 deletions(-) create mode 100644 jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/config/RefFragmentPathDelimitersIT.java create mode 100644 jsonschema2pojo-integration-tests/src/test/resources/schema/properties/nonStandardRef.json diff --git a/jsonschema2pojo-ant/src/main/java/org/jsonschema2pojo/ant/Jsonschema2PojoTask.java b/jsonschema2pojo-ant/src/main/java/org/jsonschema2pojo/ant/Jsonschema2PojoTask.java index a6673de17..b8990841d 100644 --- a/jsonschema2pojo-ant/src/main/java/org/jsonschema2pojo/ant/Jsonschema2PojoTask.java +++ b/jsonschema2pojo-ant/src/main/java/org/jsonschema2pojo/ant/Jsonschema2PojoTask.java @@ -146,6 +146,7 @@ public class Jsonschema2PojoTask extends Task implements GenerationConfig { private boolean formatDateTimes = false; + private String refFragmentPathDelimiters = "#/."; /** * Execute this task (it's expected that all relevant setters will have been @@ -696,6 +697,17 @@ public void setFormatDateTime(boolean formatDateTimes) { this.formatDateTimes = formatDateTimes; } + /** + * Sets the 'refFragmentPathDelimiters' property of this class + * + * @param refFragmentPathDelimiters A string containing any characters that should act as path delimiters when + * resolving $ref fragments. By default, #, / and . are used in an attempt + * to support JSON Pointer and JSON Path. + */ + public void setRefFragmentPathDelimiters(String refFragmentPathDelimiters) { + this.refFragmentPathDelimiters = refFragmentPathDelimiters; + } + @Override public boolean isGenerateBuilders() { return generateBuilders; @@ -938,4 +950,8 @@ public boolean isFormatDateTimes() { return formatDateTimes; } + @Override + public String getRefFragmentPathDelimiters() { + return refFragmentPathDelimiters; + } } diff --git a/jsonschema2pojo-ant/src/site/Jsonschema2PojoTask.html b/jsonschema2pojo-ant/src/site/Jsonschema2PojoTask.html index f864115c4..a0ef18ba4 100644 --- a/jsonschema2pojo-ant/src/site/Jsonschema2PojoTask.html +++ b/jsonschema2pojo-ant/src/site/Jsonschema2PojoTask.html @@ -408,6 +408,13 @@

Parameters

No (default false) + + refFragmentPathDelimiters + A string containing any characters that should act as path delimiters when resolving $ref + fragments. By default, #, / and . are used in an attempt to support JSON Pointer and JSON Path. + + No (default #/.) +

Examples

diff --git a/jsonschema2pojo-cli/src/main/java/org/jsonschema2pojo/cli/Arguments.java b/jsonschema2pojo-cli/src/main/java/org/jsonschema2pojo/cli/Arguments.java index 0e0ad99c7..1ad150bda 100644 --- a/jsonschema2pojo-cli/src/main/java/org/jsonschema2pojo/cli/Arguments.java +++ b/jsonschema2pojo-cli/src/main/java/org/jsonschema2pojo/cli/Arguments.java @@ -168,6 +168,9 @@ public class Arguments implements GenerationConfig { @Parameter(names = { "-fdt", "--format-date-times" }, description = "Whether the fields of type `date-time` have the `@JsonFormat` annotation with pattern set to the default value of `yyyy-MM-dd'T'HH:mm:ss.SSS` and timezone set to default value of `UTC`") private boolean formatDateTimes = false; + + @Parameter(names = {"-rpd", "--ref-fragment-path-delimiters"}, description = "A string containing any characters that should act as path delimiters when resolving $ref fragments. By default, #, / and . are used in an attempt to support JSON Pointer and JSON Path.") + private String refFragmentPathDelimiters = "#/."; private static final int EXIT_OKAY = 0; private static final int EXIT_ERROR = 1; @@ -418,4 +421,9 @@ public boolean isFormatDateTimes() { return formatDateTimes; } + @Override + public String getRefFragmentPathDelimiters() { + return refFragmentPathDelimiters; + } + } diff --git a/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/DefaultGenerationConfig.java b/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/DefaultGenerationConfig.java index b3234e702..fef547ce8 100644 --- a/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/DefaultGenerationConfig.java +++ b/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/DefaultGenerationConfig.java @@ -332,4 +332,12 @@ public String getTimeType() { public boolean isFormatDateTimes() { return false; } + + /** + * @return "#/." + */ + @Override + public String getRefFragmentPathDelimiters() { + return "#/."; + } } diff --git a/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/FragmentResolver.java b/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/FragmentResolver.java index 23bf5f5ff..0137f806f 100644 --- a/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/FragmentResolver.java +++ b/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/FragmentResolver.java @@ -26,9 +26,9 @@ public class FragmentResolver { - public JsonNode resolve(JsonNode tree, String path) { + public JsonNode resolve(JsonNode tree, String path, String refFragmentPathDelimiters) { - return resolve(tree, new ArrayList(asList(split(path, "#/.")))); + return resolve(tree, new ArrayList(asList(split(path, refFragmentPathDelimiters)))); } diff --git a/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/GenerationConfig.java b/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/GenerationConfig.java index a065fa5bb..03fc34358 100644 --- a/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/GenerationConfig.java +++ b/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/GenerationConfig.java @@ -441,4 +441,12 @@ public interface GenerationConfig { */ boolean isFormatDateTimes(); + /** + * Gets the `refFragmentPathDelimiters` configuration option. + * + * @return A string containing any characters that should act as path delimiters when resolving $ref fragments. + * By default, #, / and . are used in an attempt to support JSON Pointer and JSON Path. + */ + String getRefFragmentPathDelimiters(); + } diff --git a/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/SchemaStore.java b/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/SchemaStore.java index b1bb00d1b..86fbbdb0b 100644 --- a/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/SchemaStore.java +++ b/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/SchemaStore.java @@ -39,16 +39,18 @@ public class SchemaStore { * * @param id * the id of the schema being created + * @param refFragmentPathDelimiters A string containing any characters + * that should act as path delimiters when resolving $ref fragments. * @return a schema object containing the contents of the given path */ - public synchronized Schema create(URI id) { + public synchronized Schema create(URI id, String refFragmentPathDelimiters) { if (!schemas.containsKey(id)) { JsonNode content = contentResolver.resolve(removeFragment(id)); if (id.toString().contains("#")) { - JsonNode childContent = fragmentResolver.resolve(content, '#' + id.getFragment()); + JsonNode childContent = fragmentResolver.resolve(content, '#' + id.getFragment(), refFragmentPathDelimiters); schemas.put(id, new Schema(id, childContent, content)); } else { schemas.put(id, new Schema(id, content, content)); @@ -74,10 +76,12 @@ protected URI removeFragment(URI id) { * the relative path of this schema (will be used to create a * complete URI by resolving this path against the parent * schema's id) + * @param refFragmentPathDelimiters A string containing any characters + * that should act as path delimiters when resolving $ref fragments. * @return a schema object containing the contents of the given path */ @SuppressWarnings("PMD.UselessParentheses") - public Schema create(Schema parent, String path) { + public Schema create(Schema parent, String path, String refFragmentPathDelimiters) { if (!path.equals("#")) { // if path is an empty string then resolving it below results in jumping up a level. e.g. "/path/to/file.json" becomes "/path/to" @@ -109,11 +113,11 @@ public Schema create(Schema parent, String path) { } if (selfReferenceWithoutParentFile(parent, path) || substringBefore(stringId, "#").isEmpty()) { - schemas.put(id, new Schema(id, fragmentResolver.resolve(parent.getParentContent(), path), parent.getParentContent())); + schemas.put(id, new Schema(id, fragmentResolver.resolve(parent.getParentContent(), path, refFragmentPathDelimiters), parent.getParentContent())); return schemas.get(id); } - return create(id); + return create(id, refFragmentPathDelimiters); } diff --git a/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/rules/ObjectRule.java b/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/rules/ObjectRule.java index f2486b771..c11361d86 100644 --- a/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/rules/ObjectRule.java +++ b/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/rules/ObjectRule.java @@ -328,7 +328,7 @@ private Schema getSuperSchema(JsonNode node, Schema schema, boolean followRefs) path = "#" + schema.getId().getFragment() + "/extends"; } - Schema superSchema = ruleFactory.getSchemaStore().create(schema, path); + Schema superSchema = ruleFactory.getSchemaStore().create(schema, path, ruleFactory.getGenerationConfig().getRefFragmentPathDelimiters()); if (followRefs) { superSchema = resolveSchemaRefsRecursive(superSchema); @@ -342,7 +342,7 @@ private Schema getSuperSchema(JsonNode node, Schema schema, boolean followRefs) private Schema resolveSchemaRefsRecursive(Schema schema) { JsonNode schemaNode = schema.getContent(); if (schemaNode.has("$ref")) { - schema = ruleFactory.getSchemaStore().create(schema, schemaNode.get("$ref").asText()); + schema = ruleFactory.getSchemaStore().create(schema, schemaNode.get("$ref").asText(), ruleFactory.getGenerationConfig().getRefFragmentPathDelimiters()); return resolveSchemaRefsRecursive(schema); } return schema; diff --git a/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/rules/PropertyRule.java b/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/rules/PropertyRule.java index a9beda901..e565fa21b 100644 --- a/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/rules/PropertyRule.java +++ b/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/rules/PropertyRule.java @@ -147,7 +147,7 @@ private void formatAnnotation(JFieldVar field, JsonNode node) { private JsonNode resolveRefs(JsonNode node, Schema parent) { if (node.has("$ref")) { - Schema refSchema = ruleFactory.getSchemaStore().create(parent, node.get("$ref").asText()); + Schema refSchema = ruleFactory.getSchemaStore().create(parent, node.get("$ref").asText(), ruleFactory.getGenerationConfig().getRefFragmentPathDelimiters()); JsonNode refNode = refSchema.getContent(); return resolveRefs(refNode, parent); } else { diff --git a/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/rules/SchemaRule.java b/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/rules/SchemaRule.java index 84eb836d6..8dfd7ede1 100644 --- a/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/rules/SchemaRule.java +++ b/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/rules/SchemaRule.java @@ -56,7 +56,7 @@ protected SchemaRule(RuleFactory ruleFactory) { public JType apply(String nodeName, JsonNode schemaNode, JClassContainer generatableType, Schema schema) { if (schemaNode.has("$ref")) { - schema = ruleFactory.getSchemaStore().create(schema, schemaNode.get("$ref").asText()); + schema = ruleFactory.getSchemaStore().create(schema, schemaNode.get("$ref").asText(), ruleFactory.getGenerationConfig().getRefFragmentPathDelimiters()); schemaNode = schema.getContent(); if (schema.isGenerated()) { diff --git a/jsonschema2pojo-core/src/test/java/org/jsonschema2pojo/FragmentResolverTest.java b/jsonschema2pojo-core/src/test/java/org/jsonschema2pojo/FragmentResolverTest.java index 082ea6be9..174c6cadc 100644 --- a/jsonschema2pojo-core/src/test/java/org/jsonschema2pojo/FragmentResolverTest.java +++ b/jsonschema2pojo-core/src/test/java/org/jsonschema2pojo/FragmentResolverTest.java @@ -38,7 +38,7 @@ public void hashResolvesToRoot() { root.set("child2", root.objectNode()); root.set("child3", root.objectNode()); - assertThat((ObjectNode) resolver.resolve(root, "#"), is(sameInstance(root))); + assertThat((ObjectNode) resolver.resolve(root, "#", "#/."), is(sameInstance(root))); } @@ -71,17 +71,17 @@ public void slashDelimitedWordsResolveToChildNodes() { z.set("1", _1); z.set("2", _2); - assertThat((ObjectNode) resolver.resolve(root, "#/a"), is(sameInstance(a))); - assertThat((ObjectNode) resolver.resolve(root, "#/b"), is(sameInstance(b))); - assertThat((ObjectNode) resolver.resolve(root, "#/c"), is(sameInstance(c))); + assertThat((ObjectNode) resolver.resolve(root, "#/a", "#/."), is(sameInstance(a))); + assertThat((ObjectNode) resolver.resolve(root, "#/b", "#/."), is(sameInstance(b))); + assertThat((ObjectNode) resolver.resolve(root, "#/c", "#/."), is(sameInstance(c))); - assertThat((ObjectNode) resolver.resolve(root, "#/a/x"), is(sameInstance(x))); - assertThat((ObjectNode) resolver.resolve(root, "#/a/y"), is(sameInstance(y))); - assertThat((ObjectNode) resolver.resolve(root, "#/a/z"), is(sameInstance(z))); + assertThat((ObjectNode) resolver.resolve(root, "#/a/x", "#/."), is(sameInstance(x))); + assertThat((ObjectNode) resolver.resolve(root, "#/a/y", "#/."), is(sameInstance(y))); + assertThat((ObjectNode) resolver.resolve(root, "#/a/z", "#/."), is(sameInstance(z))); - assertThat((ObjectNode) resolver.resolve(root, "#/a/z/0"), is(sameInstance(_0))); - assertThat((ObjectNode) resolver.resolve(root, "#/a/z/1"), is(sameInstance(_1))); - assertThat((ObjectNode) resolver.resolve(root, "#/a/z/2"), is(sameInstance(_2))); + assertThat((ObjectNode) resolver.resolve(root, "#/a/z/0", "#/."), is(sameInstance(_0))); + assertThat((ObjectNode) resolver.resolve(root, "#/a/z/1", "#/."), is(sameInstance(_1))); + assertThat((ObjectNode) resolver.resolve(root, "#/a/z/2", "#/."), is(sameInstance(_2))); } @@ -97,9 +97,9 @@ public void pathCanReferToArrayContentsByIndex() { a.add(root.objectNode()); a.add(root.objectNode()); - assertThat(resolver.resolve(root, "#/a/0"), is(sameInstance(a.get(0)))); - assertThat(resolver.resolve(root, "#/a/1"), is(sameInstance(a.get(1)))); - assertThat(resolver.resolve(root, "#/a/2"), is(sameInstance(a.get(2)))); + assertThat(resolver.resolve(root, "#/a/0", "#/."), is(sameInstance(a.get(0)))); + assertThat(resolver.resolve(root, "#/a/1", "#/."), is(sameInstance(a.get(1)))); + assertThat(resolver.resolve(root, "#/a/2", "#/."), is(sameInstance(a.get(2)))); } @@ -111,9 +111,9 @@ public void pathCanReferToArrayContentsAtTheDocumentRoot() { root.add(root.objectNode()); root.add(root.objectNode()); - assertThat(resolver.resolve(root, "#/0"), is(sameInstance(root.get(0)))); - assertThat(resolver.resolve(root, "#/1"), is(sameInstance(root.get(1)))); - assertThat(resolver.resolve(root, "#/2"), is(sameInstance(root.get(2)))); + assertThat(resolver.resolve(root, "#/0", "#/."), is(sameInstance(root.get(0)))); + assertThat(resolver.resolve(root, "#/1", "#/."), is(sameInstance(root.get(1)))); + assertThat(resolver.resolve(root, "#/2", "#/."), is(sameInstance(root.get(2)))); } @@ -122,7 +122,7 @@ public void missingPathThrowsIllegalArgumentException() { ObjectNode root = new ObjectMapper().createObjectNode(); - resolver.resolve(root, "#/a/b/c"); + resolver.resolve(root, "#/a/b/c", "#/."); } @@ -134,7 +134,7 @@ public void attemptToUsePropertyNameOnArrayNodeThrowsIllegalArgumentException() ArrayNode a = root.arrayNode(); root.set("a", a); - resolver.resolve(root, "#/a/b"); + resolver.resolve(root, "#/a/b", "#/."); } diff --git a/jsonschema2pojo-core/src/test/java/org/jsonschema2pojo/SchemaStoreTest.java b/jsonschema2pojo-core/src/test/java/org/jsonschema2pojo/SchemaStoreTest.java index 44d7d3802..60292b581 100644 --- a/jsonschema2pojo-core/src/test/java/org/jsonschema2pojo/SchemaStoreTest.java +++ b/jsonschema2pojo-core/src/test/java/org/jsonschema2pojo/SchemaStoreTest.java @@ -36,7 +36,7 @@ public void createWithAbsolutePath() throws URISyntaxException { URI schemaUri = getClass().getResource("/schema/address.json").toURI(); - Schema schema = new SchemaStore().create(schemaUri); + Schema schema = new SchemaStore().create(schemaUri, "#/."); assertThat(schema, is(notNullValue())); assertThat(schema.getId(), is(equalTo(schemaUri))); @@ -51,8 +51,8 @@ public void createWithRelativePath() throws URISyntaxException { URI addressSchemaUri = getClass().getResource("/schema/address.json").toURI(); SchemaStore schemaStore = new SchemaStore(); - Schema addressSchema = schemaStore.create(addressSchemaUri); - Schema enumSchema = schemaStore.create(addressSchema, "enum.json"); + Schema addressSchema = schemaStore.create(addressSchemaUri, "#/."); + Schema enumSchema = schemaStore.create(addressSchema, "enum.json", "#/."); String expectedUri = removeEnd(addressSchemaUri.toString(), "address.json") + "enum.json"; @@ -68,8 +68,8 @@ public void createWithSelfRef() throws URISyntaxException { URI schemaUri = getClass().getResource("/schema/address.json").toURI(); SchemaStore schemaStore = new SchemaStore(); - Schema addressSchema = schemaStore.create(schemaUri); - Schema selfRefSchema = schemaStore.create(addressSchema, "#"); + Schema addressSchema = schemaStore.create(schemaUri, "#/."); + Schema selfRefSchema = schemaStore.create(addressSchema, "#", "#/."); assertThat(addressSchema, is(sameInstance(selfRefSchema))); @@ -81,9 +81,9 @@ public void createWithEmbeddedSelfRef() throws URISyntaxException { URI schemaUri = getClass().getResource("/schema/embeddedRef.json").toURI(); SchemaStore schemaStore = new SchemaStore(); - Schema topSchema = schemaStore.create(schemaUri); - Schema embeddedSchema = schemaStore.create(topSchema, "#/definitions/embedded"); - Schema selfRefSchema = schemaStore.create(embeddedSchema, "#"); + Schema topSchema = schemaStore.create(schemaUri, "#/."); + Schema embeddedSchema = schemaStore.create(topSchema, "#/definitions/embedded", "#/."); + Schema selfRefSchema = schemaStore.create(embeddedSchema, "#", "#/."); assertThat(topSchema, is(sameInstance(selfRefSchema))); @@ -95,8 +95,8 @@ public void createWithFragmentResolution() throws URISyntaxException { URI addressSchemaUri = getClass().getResource("/schema/address.json").toURI(); SchemaStore schemaStore = new SchemaStore(); - Schema addressSchema = schemaStore.create(addressSchemaUri); - Schema innerSchema = schemaStore.create(addressSchema, "#/properties/post-office-box"); + Schema addressSchema = schemaStore.create(addressSchemaUri, "#/."); + Schema innerSchema = schemaStore.create(addressSchema, "#/properties/post-office-box", "#/."); String expectedUri = addressSchemaUri.toString() + "#/properties/post-office-box"; @@ -114,9 +114,9 @@ public void schemaAlreadyReadIsReused() throws URISyntaxException { SchemaStore schemaStore = new SchemaStore(); - Schema schema1 = schemaStore.create(schemaUri); + Schema schema1 = schemaStore.create(schemaUri, "#/."); - Schema schema2 = schemaStore.create(schemaUri); + Schema schema2 = schemaStore.create(schemaUri, "#/."); assertThat(schema1, is(sameInstance(schema2))); @@ -130,7 +130,7 @@ public void setIfEmptyOnlySetsIfEmpty() throws URISyntaxException { URI schemaUri = getClass().getResource("/schema/address.json").toURI(); - Schema schema = new SchemaStore().create(schemaUri); + Schema schema = new SchemaStore().create(schemaUri, "#/."); schema.setJavaTypeIfEmpty(firstClass); assertThat(schema.getJavaType(), is(equalTo(firstClass))); diff --git a/jsonschema2pojo-core/src/test/java/org/jsonschema2pojo/rules/SchemaRuleTest.java b/jsonschema2pojo-core/src/test/java/org/jsonschema2pojo/rules/SchemaRuleTest.java index e011cb0c4..cfc7b7a03 100644 --- a/jsonschema2pojo-core/src/test/java/org/jsonschema2pojo/rules/SchemaRuleTest.java +++ b/jsonschema2pojo-core/src/test/java/org/jsonschema2pojo/rules/SchemaRuleTest.java @@ -24,6 +24,7 @@ import java.net.URI; import java.net.URISyntaxException; +import org.jsonschema2pojo.GenerationConfig; import org.jsonschema2pojo.Schema; import org.jsonschema2pojo.SchemaStore; import org.junit.Test; @@ -55,9 +56,13 @@ public void refsToOtherSchemasAreLoaded() throws URISyntaxException, JClassAlrea JDefinedClass jclass = new JCodeModel()._class(TARGET_CLASS_NAME); + final GenerationConfig mockGenerationConfig = mock(GenerationConfig.class); + when(mockGenerationConfig.getRefFragmentPathDelimiters()).thenReturn("#/."); + TypeRule mockTypeRule = mock(TypeRule.class); when(mockRuleFactory.getTypeRule()).thenReturn(mockTypeRule); when(mockRuleFactory.getSchemaStore()).thenReturn(new SchemaStore()); + when(mockRuleFactory.getGenerationConfig()).thenReturn(mockGenerationConfig); ArgumentCaptor captureJsonNode = ArgumentCaptor.forClass(JsonNode.class); ArgumentCaptor captureSchema = ArgumentCaptor.forClass(Schema.class); @@ -106,10 +111,14 @@ public void existingTypeIsUsedWhenTypeIsAlreadyGenerated() throws URISyntaxExcep URI schemaUri = getClass().getResource("/schema/address.json").toURI(); SchemaStore schemaStore = new SchemaStore(); - Schema schema = schemaStore.create(schemaUri); + Schema schema = schemaStore.create(schemaUri, "#/."); schema.setJavaType(previouslyGeneratedType); + final GenerationConfig mockGenerationConfig = mock(GenerationConfig.class); + when(mockGenerationConfig.getRefFragmentPathDelimiters()).thenReturn("#/."); + when(mockRuleFactory.getSchemaStore()).thenReturn(schemaStore); + when(mockRuleFactory.getGenerationConfig()).thenReturn(mockGenerationConfig); ObjectNode schemaNode = new ObjectMapper().createObjectNode(); schemaNode.put("$ref", schemaUri.toString()); diff --git a/jsonschema2pojo-gradle-plugin/src/main/groovy/org/jsonschema2pojo/gradle/JsonSchemaExtension.groovy b/jsonschema2pojo-gradle-plugin/src/main/groovy/org/jsonschema2pojo/gradle/JsonSchemaExtension.groovy index 7842c3100..7161f243d 100644 --- a/jsonschema2pojo-gradle-plugin/src/main/groovy/org/jsonschema2pojo/gradle/JsonSchemaExtension.groovy +++ b/jsonschema2pojo-gradle-plugin/src/main/groovy/org/jsonschema2pojo/gradle/JsonSchemaExtension.groovy @@ -73,6 +73,7 @@ public class JsonSchemaExtension implements GenerationConfig { boolean usePrimitives FileFilter fileFilter boolean formatDateTimes + String refFragmentPathDelimiters public JsonSchemaExtension() { // See DefaultGenerationConfig @@ -116,6 +117,7 @@ public class JsonSchemaExtension implements GenerationConfig { targetVersion = '1.6' includeDynamicAccessors = false formatDateTimes = false + refFragmentPathDelimiters = "#/." } @Override @@ -201,11 +203,12 @@ public class JsonSchemaExtension implements GenerationConfig { |targetVersion = ${targetVersion} |includeDynamicAccessors = ${includeDynamicAccessors} |formatDateTimes = ${formatDateTimes} + |refFragmentPathDelimiters = ${refFragmentPathDelimiters} """.stripMargin() } public boolean isFormatDateTimes() { return formatDateTimes; } - + } diff --git a/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/config/RefFragmentPathDelimitersIT.java b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/config/RefFragmentPathDelimitersIT.java new file mode 100644 index 000000000..e2ddacf43 --- /dev/null +++ b/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/config/RefFragmentPathDelimitersIT.java @@ -0,0 +1,37 @@ +/** + * Copyright © 2010-2014 Nokia + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jsonschema2pojo.integration.config; + +import org.jsonschema2pojo.integration.util.Jsonschema2PojoRule; +import org.junit.Rule; +import org.junit.Test; + +import static org.jsonschema2pojo.integration.util.CodeGenerationHelper.config; + +public class RefFragmentPathDelimitersIT { + + @Rule public Jsonschema2PojoRule schemaRule = new Jsonschema2PojoRule(); + + @Test + public void refFragmentPathDelimitersUsedInAPropertyIsReadSuccessfully() throws ClassNotFoundException, SecurityException, NoSuchMethodException { + + ClassLoader resultsClassLoader = schemaRule.generateAndCompile("/schema/properties/nonStandardRef.json", "com.example", + config("refFragmentPathDelimiters", "#/")); + + resultsClassLoader.loadClass("com.example.Foo"); + } +} diff --git a/jsonschema2pojo-integration-tests/src/test/resources/schema/properties/nonStandardRef.json b/jsonschema2pojo-integration-tests/src/test/resources/schema/properties/nonStandardRef.json new file mode 100644 index 000000000..87bce4352 --- /dev/null +++ b/jsonschema2pojo-integration-tests/src/test/resources/schema/properties/nonStandardRef.json @@ -0,0 +1,19 @@ +{ + "type" : "object", + "properties" : { + "foo" : { + "$ref" : "#/definitions/com.example.Foo" + } + }, + "additionalProperties" : false, + "definitions" : { + "com.example.Foo" : { + "type" : "object", + "properties" : { + "bar" : { + "type" : "string" + } + } + } + } +} \ No newline at end of file diff --git a/jsonschema2pojo-maven-plugin/src/main/java/org/jsonschema2pojo/maven/Jsonschema2PojoMojo.java b/jsonschema2pojo-maven-plugin/src/main/java/org/jsonschema2pojo/maven/Jsonschema2PojoMojo.java index f6578da77..325fe979f 100644 --- a/jsonschema2pojo-maven-plugin/src/main/java/org/jsonschema2pojo/maven/Jsonschema2PojoMojo.java +++ b/jsonschema2pojo-maven-plugin/src/main/java/org/jsonschema2pojo/maven/Jsonschema2PojoMojo.java @@ -579,6 +579,15 @@ public class Jsonschema2PojoMojo extends AbstractMojo implements GenerationConfi */ private boolean formatDateTimes = false; + /** + * A string containing any characters that should act as path delimiters when resolving $ref fragments. + * By default, #, / and . are used in an attempt to support JSON Pointer and JSON Path. + * + * @parameter expression="${jsonschema2pojo.refFragmentPathDelimiters}" default-value="#/." + * @since 0.4.31 + */ + private String refFragmentPathDelimiters = "#/."; + private FileFilter fileFilter = new AllFileFilter(); /** @@ -917,4 +926,9 @@ public boolean isFormatDateTimes() { return formatDateTimes; } + @Override + public String getRefFragmentPathDelimiters() { + return refFragmentPathDelimiters; + } + }