Skip to content

Commit

Permalink
Jackson corrections. See #175 #169 #167
Browse files Browse the repository at this point in the history
  • Loading branch information
elucash committed Oct 20, 2015
1 parent c05540d commit 09e4f1c
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 49 deletions.
Expand Up @@ -15,13 +15,15 @@
*/
package org.immutables.fixture.jackson;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.util.List;
import org.immutables.value.Value;

@Value.Immutable
@JsonDeserialize(as = ImmutableMinimumAnnotationsMapped.class)
@JsonIgnoreProperties(ignoreUnknown = true)
public interface MinimumAnnotationsMapped {
@JsonProperty("A")
String a();
Expand Down
@@ -0,0 +1,39 @@
package org.immutables.fixture.jackson;

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.immutables.value.Value;

public interface PolymorphicMappings {
@JsonSubTypes({
@Type(DatasetIdLocator.class),
@Type(DatasetPathLocator.class),
@Type(ImmutableDatasetIdLocator.class),
@Type(ImmutableDatasetPathLocator.class)
})
@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "@class", visible = false)
public interface DatasetLocator {}

@Value.Immutable
@Value.Style(visibility = Value.Style.ImplementationVisibility.PACKAGE)
@JsonSerialize(as = ImmutableDatasetIdLocator.class)
@JsonDeserialize(as = ImmutableDatasetIdLocator.class)
public interface DatasetIdLocator extends DatasetLocator {
String getDatasetId();
class Builder extends ImmutableDatasetIdLocator.Builder {}
}

@Value.Immutable
@Value.Style(visibility = Value.Style.ImplementationVisibility.PACKAGE)
@JsonSerialize(as = ImmutableDatasetIdLocator.class)
@JsonDeserialize(as = ImmutableDatasetIdLocator.class)
public interface DatasetPathLocator extends DatasetLocator {
String getDatasetPath();
class Builder extends ImmutableDatasetPathLocator.Builder {}
}
}
Expand Up @@ -55,6 +55,15 @@ public void minimumMarshaledPropertyNames() throws IOException {
check(OBJECT_MAPPER.readValue(json, ImmutableMinimumAnnotationsMapped.class)).is(mapped);
}

@Test
public void minimumIgnoreUnknownNames() throws IOException {
String originalSampleJson = "{\"A\":\"a\", \"B\": [1, 2], \"Z\": false}";
ImmutableMinimumAnnotationsMapped mapped =
OBJECT_MAPPER.readValue(originalSampleJson, ImmutableMinimumAnnotationsMapped.class);
String json = OBJECT_MAPPER.writeValueAsString(mapped);
check(OBJECT_MAPPER.readValue(json, ImmutableMinimumAnnotationsMapped.class)).is(mapped);
}

@Test
public void topLevelMarshalUnmarshal() throws IOException {
ImmutableSampleJacksonMapped mapped = ImmutableSampleJacksonMapped.builder().a("a").addB(1, 2).build();
Expand Down
@@ -0,0 +1,20 @@
package org.immutables.fixture.jackson;

import static org.immutables.check.Checkers.*;
import org.immutables.fixture.jackson.PolymorphicMappings.DatasetLocator;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import org.immutables.fixture.jackson.PolymorphicMappings.DatasetIdLocator;
import org.junit.Test;

public class PolymorphicTest {
ObjectMapper om = new ObjectMapper();

@Test
public void polymorphic() throws IOException {
DatasetIdLocator locator = new DatasetIdLocator.Builder().datasetId("id").build();
DatasetLocator value = om.readValue(om.writeValueAsBytes(locator), DatasetLocator.class);
check(value).isA(DatasetIdLocator.class);
check(((DatasetIdLocator) value).getDatasetId()).is(locator.getDatasetId());
}
}
Expand Up @@ -1396,6 +1396,9 @@ this.[v.name] = [requireNonNull type]([invokeSuper v].[v.names.get]());
* Simple representation of this value type suitable Jackson binding
* @deprecated Do not use this type directly, it exists only for <em>Jackson</em>-binding infrastructure
*/
[for a in type.passedJsonAnnotations]
[a]
[/for]
@Deprecated
static final class Json {
[for v in type.implementedAttributes]
Expand All @@ -1406,19 +1409,6 @@ static final class Json {
[/for]
}

/**
* @return JSON-bindable data structure
* @deprecated Do not use this method directly, it exists only for <em>Jackson</em>-binding infrastructure
*/
@Deprecated
@com.fasterxml.jackson.annotation.JsonValue
Json [disambiguateAccessor type 'toJson']() {
Json json = new Json();
[for v in type.implementedAttributes]
json.[v.name] = this.[v.name];
[/for]
return json;
}
[/if]

/**
Expand Down
Expand Up @@ -36,6 +36,8 @@ private Annotations() {}
private static final String PREFIX_IMMUTABLES = "org.immutables.";
private static final String PREFIX_JACKSON = "com.fasterxml.jackson.annotation.";
private static final String PREFIX_JACKSON_DATABIND = "com.fasterxml.jackson.databind.annotation.";
private static final String PREFIX_JACKSON_IGNORE_PROPERTIES =
"com.fasterxml.jackson.annotation.JsonIgnoreProperties";

static final String NULLABLE_SIMPLE_NAME = "Nullable";

Expand Down Expand Up @@ -74,6 +76,12 @@ private static boolean annotationTypeMatches(
// we expect to propagate nullability separately
return false;
}

if (qualifiedName.equals(PREFIX_JACKSON_IGNORE_PROPERTIES)) {
// this is just very often used exception
// but preferred way is to use additionalJsonAnnotations style attribute.
return true;
}

if (includeJacksonAnnotations
&& (qualifiedName.startsWith(PREFIX_JACKSON) || qualifiedName.startsWith(PREFIX_JACKSON_DATABIND))) {
Expand Down
Expand Up @@ -23,7 +23,6 @@
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

import java.lang.annotation.ElementType;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -220,45 +219,43 @@ public String getType() {
}

public List<CharSequence> getAnnotations() {
return Annotations.getAnnotationLines(element,
Sets.union(containingType.constitution.protoclass().styles().style().passAnnotationsNames(), containingType.constitution.protoclass().styles().style().additionalJsonAnnotationsNames()),
false,
ElementType.METHOD);
}
if (containingType.isGenerateJacksonMapped()) {
return extractAnnotationsForElement(
ElementType.METHOD,
containingType.constitution.protoclass().styles().style().passAnnotationsNames());

public List<CharSequence> getParameterAnnotations() {
return Annotations.getAnnotationLines(element,
Sets.union(containingType.constitution.protoclass().styles().style().passAnnotationsNames(), containingType.constitution.protoclass().styles().style().additionalJsonAnnotationsNames()),
false,
ElementType.PARAMETER);
} else {
return Annotations.getAnnotationLines(element,
containingType.constitution.protoclass().styles().style().passAnnotationsNames(),
false,
ElementType.METHOD);
}
}

public List<CharSequence> getJacksonFieldsAnnotations() {
List<CharSequence> jsonPropertyAnnotation = Annotations.getAnnotationLines(element,
Collections.singleton(JsonPropertyMirror.QUALIFIED_NAME),
false,
ElementType.FIELD);
return extractAnnotationsForElement(ElementType.FIELD, Collections.<String>emptySet());
}

List<CharSequence> appendedJsonPropertyAnnotation = Lists.newArrayListWithCapacity(1);
private List<CharSequence> extractAnnotationsForElement(ElementType elementType, Set<String> additionalAnnotations) {
List<CharSequence> allAnnotations = Lists.newArrayListWithCapacity(1);

if (jsonPropertyAnnotation.isEmpty()) {
appendedJsonPropertyAnnotation.add("@" + JsonPropertyMirror.qualifiedName());
}

List<CharSequence> additionalJsonAnnotations = Annotations.getAnnotationLines(element,
containingType.constitution.protoclass().styles().style().additionalJsonAnnotationsNames(),
boolean dontHaveJsonPropetyAnnotationAlready = Annotations.getAnnotationLines(element,
Collections.singleton(JsonPropertyMirror.qualifiedName()),
false,
ElementType.FIELD);
elementType).isEmpty();

if (dontHaveJsonPropetyAnnotationAlready) {
allAnnotations.add("@" + JsonPropertyMirror.qualifiedName());
}

List<CharSequence> allJacksonAnnotations = Annotations.getAnnotationLines(element,
Collections.<String>emptySet(),
true,
ElementType.FIELD);
allAnnotations.addAll(
Annotations.getAnnotationLines(element,
Sets.union(additionalAnnotations,
containingType.constitution.protoclass().styles().style().additionalJsonAnnotationsNames()),
true,
elementType));

return FluentIterable.from(allJacksonAnnotations)
.append(appendedJsonPropertyAnnotation)
.append(additionalJsonAnnotations)
.toList();
return allAnnotations;
}

public boolean isGsonIgnore() {
Expand Down Expand Up @@ -822,8 +819,7 @@ private void initTypeKind() {
}

DeclaringType getDeclaringType() {
@Nullable
TypeElement declaringType = null;
@Nullable TypeElement declaringType = null;
for (Element e = element; e != null;) {
e = e.getEnclosingElement();
if (e instanceof TypeElement) {
Expand Down Expand Up @@ -918,8 +914,7 @@ private void initMiscellaneous() {
this.deprecated = elements.isDeprecated(element);

if (containingType.constitution.implementationVisibility().isPublic()) {
@Nullable
String docComment = elements.getDocComment(element);
@Nullable String docComment = elements.getDocComment(element);
if (docComment != null) {
this.docComment = ImmutableList.copyOf(DOC_COMMENT_LINE_SPLITTER.split(docComment));
}
Expand Down
Expand Up @@ -282,10 +282,24 @@ private List<Element> includedElements(TransformMirror transform) {
return includedElements;
}

public List<CharSequence> passedJsonAnnotations() {
return Annotations.getAnnotationLines(
element,
constitution.protoclass()
.styles()
.style()
.additionalJsonAnnotationsNames(),
false,
ElementType.TYPE);
}

public List<CharSequence> passedAnnotations() {
return Annotations.getAnnotationLines(
element,
Sets.union(constitution.protoclass().styles().style().passAnnotationsNames(), constitution.protoclass().styles().style().additionalJsonAnnotationsNames()),
Sets.union(constitution.protoclass().styles().style().passAnnotationsNames(), constitution.protoclass()
.styles()
.style()
.additionalJsonAnnotationsNames()),
false,
ElementType.TYPE);
}
Expand Down

0 comments on commit 09e4f1c

Please sign in to comment.