Skip to content

Commit

Permalink
Merge pull request #39 from wuan/type_deserialization
Browse files Browse the repository at this point in the history
type deserialization support
  • Loading branch information
JoergAdler committed Apr 5, 2017
2 parents 93561cd + cc42e3a commit 518d48c
Show file tree
Hide file tree
Showing 15 changed files with 356 additions and 38 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Expand Up @@ -36,7 +36,7 @@
</scm>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jackson.version>2.7.5</jackson.version>
<jackson.version>2.7.9</jackson.version>
<jmh.version>1.12</jmh.version>
</properties>
<developers>
Expand Down
Expand Up @@ -99,4 +99,11 @@ public static JsonHyperSchema fromOptional(Collection<Optional<Link>> links) {
private static <T> Stream<T> filterOptionals(Stream<Optional<T>> streamWithOptionals) {
return streamWithOptionals.filter(Objects::nonNull).flatMap(e -> e.map(Stream::of).orElse(Stream.empty()));
}

@Override
public String toString() {
return "JsonHyperSchema{" +
"links=" + links +
'}';
}
}
Expand Up @@ -2,12 +2,18 @@

import java.util.List;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.mercateo.common.rest.schemagen.JsonHyperSchema;

@JsonIgnoreProperties("object")
public class ListResponse<T> extends ObjectWithSchema<WrappedList<ObjectWithSchema<T>>> {

protected ListResponse(List<ObjectWithSchema<T>> members, JsonHyperSchema schema) {
super(new WrappedList<>(members), schema);
@JsonCreator
protected ListResponse(@JsonProperty("members") List<ObjectWithSchema<T>> members,
@JsonProperty("_schema") JsonHyperSchema schema) {
super(new WrappedList<>(members), schema, null);
}

@Override
Expand All @@ -20,7 +26,12 @@ public static <T> ListResponse<T> create(List<ObjectWithSchema<T>> members, Json
}

public static <ElementIn, ElementOut> ListResponseBuilder<ElementIn, ElementOut> builder() {
//noinspection deprecation
// noinspection deprecation
return new ListResponseBuilder<>();
}

@JsonProperty("members")
public List<ObjectWithSchema<T>> getMembers() {
return object.members;
}
}
Expand Up @@ -2,9 +2,11 @@

import static java.util.Objects.requireNonNull;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
Expand All @@ -23,20 +25,38 @@ public class ObjectWithSchema<T> {
@JsonProperty("_messages")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@IgnoreInRestSchema
public List<Message> messages;
public final List<Message> messages;

ObjectWithSchema(T object, JsonHyperSchema schema, List<Message> messages) {
@JsonCreator
protected ObjectWithSchema(@JsonProperty("object") T object, @JsonProperty("_schema") JsonHyperSchema schema,
@JsonProperty("_messages") List<Message> messages) {
// this has to be null, if T is Void, so please, do not "fix" this!
this.object = object;
this.schema = requireNonNull(schema);
this.messages = requireNonNull(messages);
this.messages = messages != null ? messages : Collections.emptyList();
}

protected ObjectWithSchema(T object, JsonHyperSchema schema) {
this(object, schema, new ArrayList<>());
public static <U> ObjectWithSchema<U> create(U object, JsonHyperSchema schema) {
return new ObjectWithSchema<>(object, schema, null);
}

public static <U> ObjectWithSchema<U> create(U object, JsonHyperSchema schema) {
return new ObjectWithSchema<>(object, schema);
@JsonIgnore
public JsonHyperSchema getSchema() {
return schema;
}

@JsonIgnore
public List<Message> getMessages() {
return messages;
}

@JsonIgnore
public T getObject() {
return object;
}

@Override
public String toString() {
return "ObjectWithSchema{" + "object=" + object + ", schema=" + schema + ", messages=" + messages + '}';
}
}
@@ -1,5 +1,9 @@
package com.mercateo.common.rest.schemagen.types;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.glassfish.jersey.server.JSONP;

import java.util.List;

public class PaginatedList<T> {
Expand All @@ -11,7 +15,8 @@ public class PaginatedList<T> {

public final int limit;

public PaginatedList(int total, int offset, int limit, List<T> members) {
@JsonCreator
public PaginatedList(@JsonProperty("total") int total, @JsonProperty("offset") int offset, @JsonProperty("limit") int limit, @JsonProperty("members") List<T> members) {
this.total = total;
this.offset = offset;
this.limit = limit;
Expand Down
Expand Up @@ -3,31 +3,60 @@
import java.util.List;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.mercateo.common.rest.schemagen.JsonHyperSchema;

@JsonIgnoreProperties("object")
public class PaginatedResponse<T> extends ObjectWithSchema<PaginatedList<ObjectWithSchema<T>>> {

@JsonIgnore
public static final int DEFAULT_LIMIT = 2000;

protected PaginatedResponse(List<ObjectWithSchema<T>> members, int total, int offset, int limit, JsonHyperSchema schema) {
super(new PaginatedList<>(total, offset, limit, members), schema);

protected PaginatedResponse(@JsonProperty("members") List<ObjectWithSchema<T>> members,
@JsonProperty("total") int total, @JsonProperty("offset") int offset, @JsonProperty("limit") int limit,
@JsonProperty("_schema") JsonHyperSchema schema) {
super(new PaginatedList<>(total, offset, limit, members), schema, null);
}

@Override
public String toString() {
return "PaginatedResponse [ payload=" + object.members + ", offset=" + object.offset + ", _schema=" + schema + "]";
return "PaginatedResponse [ payload=" + object.members + ", offset=" + object.offset + ", _schema=" + schema
+ "]";
}

public static <U> PaginatedResponse<U> create(List<ObjectWithSchema<U>> members, int total, int offset, int limit, JsonHyperSchema schema) {
public static <U> PaginatedResponse<U> create(List<ObjectWithSchema<U>> members, int total, int offset, int limit,
JsonHyperSchema schema) {
return new PaginatedResponse<>(members, total, offset, limit, schema);
}

public static <U> PaginatedResponse<U> create(PaginatedList<ObjectWithSchema<U>> paginatedList, JsonHyperSchema schema) {
return new PaginatedResponse<>(paginatedList.members, paginatedList.total, paginatedList.offset, paginatedList.limit, schema);
public static <U> PaginatedResponse<U> create(PaginatedList<ObjectWithSchema<U>> paginatedList,
JsonHyperSchema schema) {
return new PaginatedResponse<>(paginatedList.members, paginatedList.total, paginatedList.offset,
paginatedList.limit, schema);
}

public static <ElementIn, ElementOut> PaginatedResponseBuilder<ElementIn, ElementOut> builder() {
return new PaginatedResponseBuilder<>();
}

@JsonProperty("members")
public List<ObjectWithSchema<T>> getMembers() {
return object.members;
}

@JsonProperty("offset")
public Integer getOffset() {
return object.offset;
}

@JsonProperty("limit")
public Integer getLimit() {
return object.limit;
}

@JsonProperty("total")
public Integer getTotal() {
return object.total;
}
}
@@ -1,5 +1,6 @@
package com.mercateo.common.rest.schemagen.types;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonUnwrapped;

Expand All @@ -13,9 +14,10 @@ public class WithId<T> {
@JsonUnwrapped
public final T object;

@JsonCreator
private WithId(
@JsonProperty("id") UUID id,
@JsonProperty("name") T object
@JsonProperty("object") T object
) {
this.id = id;
this.object = object;
Expand Down
Expand Up @@ -2,11 +2,15 @@

import java.util.List;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public class WrappedList<T> {

public final List<T> members;

public WrappedList(List<T> members) {
@JsonCreator
public WrappedList(@JsonProperty("members") List<T> members) {
this.members = members;
}

Expand Down
Expand Up @@ -10,6 +10,7 @@
import com.mercateo.common.rest.schemagen.parameter.CallContext;
import com.mercateo.common.rest.schemagen.types.ListResponse;
import com.mercateo.common.rest.schemagen.types.ObjectWithSchema;
import com.mercateo.common.rest.schemagen.types.WrappedList;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand Down Expand Up @@ -695,7 +696,6 @@ public static class UUIDSchemaObject {
}

public static class ListObject extends ListResponse<SchemaObject> {

protected ListObject(List<ObjectWithSchema<SchemaObject>> members, JsonHyperSchema schema) {
super(members, schema);
}
Expand Down Expand Up @@ -731,13 +731,13 @@ public static class UnwrappedObject {

public static class MessageResponse extends ObjectWithSchema<String> {
MessageResponse(String object, JsonHyperSchema schema) {
super(object, schema);
super(object, schema, null);
}
}

public static class WrappedObject extends ObjectWithSchema<SchemaObject> {
protected WrappedObject(SchemaObject object, JsonHyperSchema schema) {
super(object, schema);
super(object, schema, null);
}
}

Expand Down
Expand Up @@ -21,7 +21,7 @@ public class GenericParameterizedTypeTest extends ObjectWithSchema<Boolean> {

@SuppressWarnings("boxing")
public GenericParameterizedTypeTest() {
super(true, new JsonHyperSchema(new ArrayList<>()));
super(true, new JsonHyperSchema(new ArrayList<>()), null);
}

@Test
Expand Down
Expand Up @@ -5,41 +5,87 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.ws.rs.core.Link;

import org.junit.Test;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.mercateo.common.rest.schemagen.JsonHyperSchema;

public class ListResponseTest {

@Test
public void testListResponseBuilder() {

Link containerLink = Link.fromPath( "/").build();
final ListResponse<String> listResponse = ListResponse.<Integer, String> builder()
.withList(Arrays.asList(1, 2, 3)).withElementMapper(this::elementMapper)
.withContainerLinks(containerLink).build();
Link containerLink = Link.fromPath("/").build();
final ListResponse<String> listResponse = ListResponse
.<Integer, String> builder()
.withList(Arrays.asList(1, 2, 3))
.withElementMapper(this::elementMapper)
.withContainerLinks(containerLink)
.build();

final List<String> strings = listResponse.object.members.stream().map(o -> o.object)
.collect(Collectors.toList());
final List<String> strings = listResponse.object.members.stream().map(o -> o.object).collect(Collectors
.toList());
assertThat(strings).containsExactly("1", "2", "3");

final List<String> links = listResponse.object.members.stream().map(
o -> o.schema.getLinks().iterator().next().getUri().toString()).collect(
Collectors.toList());
final List<String> links = listResponse.object.members
.stream()
.map(o -> o.schema.getLinks().iterator().next().getUri().toString())
.collect(Collectors.toList());
assertThat(links).containsExactly("/1", "/2", "/3");

assertThat(listResponse.schema.getLinks().iterator().next().getUri().toString()).isEqualTo(
"/");
assertThat(listResponse.schema.getLinks().iterator().next().getUri().toString()).isEqualTo("/");
}

private ObjectWithSchema<String> elementMapper(Integer number) {
final Link link = Link.fromPath("/" + number).build();
return ObjectWithSchema.create(Integer.toHexString(number), JsonHyperSchema.from(link));
}

static class Payload {
public String value;
}

@Test
public void shouldSerializ() throws Exception {
final ObjectMapper objectMapper = new ObjectMapper();

final Payload payload = new Payload();
payload.value = "foo";
final ObjectWithSchema<Payload> element = ObjectWithSchema.create(payload, JsonHyperSchema.from(Collections
.emptyList()));
final ListResponse<Payload> listResponse = new ListResponse<>(Collections.singletonList(element),
JsonHyperSchema.from(Collections.emptyList()));

final String jsonString = objectMapper.writeValueAsString(listResponse);

assertThat(jsonString).isEqualTo(
"{\"members\":[{\"value\":\"foo\",\"_schema\":{\"links\":[]}}],\"_schema\":{\"links\":[]}}");
}

@Test
public void shouldDeserialize() throws Exception {
final ObjectMapper mapper = new ObjectMapper();
mapper.disableDefaultTyping();

final String content = "{\"members\": [{\"value\": \"foo\", \"_schema\":{\"links\":[]}}, {\"value\": \"bar\", \"_schema\":{\"links\":[]}}], \"_schema\":{\"links\":[]}}";

final ListResponse<Payload> listResponse = mapper.readValue(content,
new TypeReference<ListResponse<Payload>>() {
});

assertThat(listResponse.getMembers())
.extracting(ObjectWithSchema::getObject)
.extracting(p -> p.value)
.containsExactly("foo", "bar");
}



}

0 comments on commit 518d48c

Please sign in to comment.