Skip to content

Commit

Permalink
Serialize as a JSON string, not raw
Browse files Browse the repository at this point in the history
  • Loading branch information
trickl committed Sep 13, 2019
1 parent 9f52a9f commit dd33157
Show file tree
Hide file tree
Showing 13 changed files with 110 additions and 96 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ private static class TypedExample {

// To produce "?valueA=test&valueB=testB&valueC=123"...
TypedQuery typed = new TypedQuery(... // omitted for brevity
String queryString = objectMapper.writeValueAsString(typedQuery);
String queryString = objectMapper.valueToTree(typedQuery).textValue();
```

### Features
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.trickl</groupId>
<artifactId>jackson.module.httpquery</artifactId>
<version>1.0.1-SNAPSHOT</version>
<version>1.0.2-SNAPSHOT</version>
<packaging>jar</packaging>
<developers>
<developer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.lang.reflect.Array;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
Expand Down Expand Up @@ -54,98 +55,111 @@ public final void serialize(Object bean, JsonGenerator gen, SerializerProvider p
beanSerializer.properties().forEachRemaining((prop) -> propList.add((BeanPropertyWriter) prop));
BeanPropertyWriter[] props = propList.toArray(new BeanPropertyWriter[0]);

List<String> nameValueParams = new ArrayList<>();
int i = 0;
boolean propertyWritten = false;
try {
for (final int len = props.length; i < len; ++i) {
if (i == 0 && includeQuestionMark) {
gen.writeRaw("?");
} else if (propertyWritten) {
gen.writeRaw("&");
}

BeanPropertyWriter prop = props[i];
if (prop != null) { // can have nulls in filtered list
propertyWritten = serializeAsNameValue(bean, prop, gen, provider);
String nameValueParam = writeNameValueAsString(bean, prop, provider);
if (nameValueParam != null && nameValueParam.length() > 0) {
nameValueParams.add(nameValueParam);
}
}
}
} catch (Exception e) {
String name = (i == props.length) ? "[anySetter]" : props[i].getName();
wrapAndThrow(provider, e, bean, name);
}

String query = nameValueParams.stream().collect(Collectors.joining("&"));
if (includeQuestionMark) {
query = "?" + query;
}
gen.writeString(query);
}

/** Write a property out as "name=value". */
public String writeNameValueAsString(
Object bean, BeanPropertyWriter prop, SerializerProvider provider) throws Exception {
StringWriter writer = new StringWriter();
writeNameValue(writer, bean, prop, provider);
return writer.toString();
}

/** Write a property out as "name=value". */
public boolean serializeAsNameValue(
Object bean, BeanPropertyWriter prop, JsonGenerator gen, SerializerProvider provider)
public void writeNameValue(
Writer nameValueWriter, Object bean, BeanPropertyWriter prop, SerializerProvider provider)
throws Exception {

JsonFactory jsonFactory = new JsonFactory();
StringWriter valueWriter = new StringWriter();
Object propValue = prop.get(bean);
String propName = prop.getName();
JavaType propType = prop.getType();
String name = encodeNames ? encode(propName) : propName;

try (QuotelessStringGenerator valueGenerator =
new QuotelessStringGenerator(jsonFactory.createGenerator(valueWriter))) {

HttpQueryNoValue annotatedNoValue = prop.findAnnotation(HttpQueryNoValue.class);
if (annotatedNoValue != null) {
if (propValue != null && !Boolean.FALSE.equals(propValue)) {
gen.writeRaw(name);
return true;
} else {
return false;
}
} else if (propValue == null) {
if (prop.willSuppressNulls()) {
return false;
} else {
provider.findNullValueSerializer(prop).serialize(propValue, valueGenerator, provider);
}
} else if (propType.isTypeOrSubTypeOf(Collection.class) || propType.isArrayType()) {
Collection<?> collection = Collections.emptyList();
if (propType.isTypeOrSubTypeOf(Collection.class)) {
collection = (Collection<?>) propValue;
} else {
AtomicInteger index = new AtomicInteger(0);
collection =
Stream.generate(() -> Array.get(propValue, index.getAndIncrement()))
.limit(Array.getLength(propValue))
.collect(Collectors.toList());
}

HttpQueryDelimited annotatedList = prop.findAnnotation(HttpQueryDelimited.class);
if (annotatedList != null) {
HttpQueryDelimitedSerializer serializer =
new HttpQueryDelimitedSerializer(
propType,
annotatedList.delimiter(),
annotatedList.encodeDelimiter(),
encodeValues);
gen.writeRaw(name);
gen.writeRaw("=");
serializer.serialize(collection, gen, provider);
return true;
StringWriter valueWriter = new StringWriter();
try (JsonGenerator gen = jsonFactory.createGenerator(nameValueWriter)) {
try (QuotelessStringGenerator valueGenerator =
new QuotelessStringGenerator(jsonFactory.createGenerator(valueWriter))) {

HttpQueryNoValue annotatedNoValue = prop.findAnnotation(HttpQueryNoValue.class);
if (annotatedNoValue != null) {
if (propValue != null && !Boolean.FALSE.equals(propValue)) {
gen.writeRaw(name);
return;
} else {
return;
}
} else if (propValue == null) {
if (prop.willSuppressNulls()) {
return;
} else {
provider.findNullValueSerializer(prop).serialize(propValue, valueGenerator, provider);
}
} else if (propType.isTypeOrSubTypeOf(Collection.class) || propType.isArrayType()) {
Collection<?> collection = Collections.emptyList();
if (propType.isTypeOrSubTypeOf(Collection.class)) {
collection = (Collection<?>) propValue;
} else {
AtomicInteger index = new AtomicInteger(0);
collection =
Stream.generate(() -> Array.get(propValue, index.getAndIncrement()))
.limit(Array.getLength(propValue))
.collect(Collectors.toList());
}

HttpQueryDelimited annotatedList = prop.findAnnotation(HttpQueryDelimited.class);
if (annotatedList != null) {
HttpQueryDelimitedSerializer serializer =
new HttpQueryDelimitedSerializer(
propType,
annotatedList.delimiter(),
annotatedList.encodeDelimiter(),
encodeValues);
gen.writeRaw(name);
gen.writeRaw("=");
serializer.serialize(collection, gen, provider);
return;
} else {
HttpQueryCollectionSerializer serializer =
new HttpQueryCollectionSerializer(prop, encodeNames, encodeValues);
serializer.serialize(collection, gen, provider);
return;
}
} else {
HttpQueryCollectionSerializer serializer =
new HttpQueryCollectionSerializer(prop, encodeNames, encodeValues);
serializer.serialize(collection, gen, provider);
return true;
Class<?> cls = propValue.getClass();
provider
.findTypedValueSerializer(cls, true, prop)
.serialize(propValue, valueGenerator, provider);
}
} else {
Class<?> cls = propValue.getClass();
provider
.findTypedValueSerializer(cls, true, prop)
.serialize(propValue, valueGenerator, provider);
}
}

String value = valueWriter.getBuffer().toString();
gen.writeRaw(name);
gen.writeRaw("=");
gen.writeRaw(encodeValues ? encode(value) : value);
return true;
String value = valueWriter.toString();
gen.writeRaw(name);
gen.writeRaw("=");
gen.writeRaw(encodeValues ? encode(value) : value);
}
}

private String encode(String value) throws UnsupportedEncodingException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public CustomDelimiterNoEncodeArrayQuery(String[] values) {
public void testRegularArraySerialization() throws JsonProcessingException {
assertEquals(
"?paramA=first&paramA=second&paramA=third",
objectMapper.writeValueAsString(new RegularArrayQuery(EXAMPLE_ARRAY)));
objectMapper.valueToTree(new RegularArrayQuery(EXAMPLE_ARRAY)).textValue());
}

@Test
Expand All @@ -114,7 +114,7 @@ public void testRegularArrayDeserialization() throws IOException {
public void testDelimitedArraySerialization() throws JsonProcessingException {
assertEquals(
"?paramA=first%2Csecond%2Cthird",
objectMapper.writeValueAsString(new DelimitedArrayQuery(EXAMPLE_ARRAY)));
objectMapper.valueToTree(new DelimitedArrayQuery(EXAMPLE_ARRAY)).textValue());
}

@Test
Expand All @@ -128,7 +128,7 @@ public void testDelimitedArrayDeserialization() throws IOException {
public void testDelimitedArrayNoEncodeSerialization() throws JsonProcessingException {
assertEquals(
"?paramA=first,second,third",
objectMapper.writeValueAsString(new DelimitedArrayNoEncodeQuery(EXAMPLE_ARRAY)));
objectMapper.valueToTree(new DelimitedArrayNoEncodeQuery(EXAMPLE_ARRAY)).textValue());
}

@Test
Expand All @@ -143,7 +143,7 @@ public void testDelimitedArrayNoEncodeDeserialization() throws IOException {
public void testCustomDelimiterArraySerialization() throws JsonProcessingException {
assertEquals(
"?paramA=first%3Bsecond%3Bthird",
objectMapper.writeValueAsString(new CustomDelimiterArrayQuery(EXAMPLE_ARRAY)));
objectMapper.valueToTree(new CustomDelimiterArrayQuery(EXAMPLE_ARRAY)).textValue());
}

@Test
Expand All @@ -158,7 +158,7 @@ public void testCustomDelimiterArrayDeserialization() throws IOException {
public void testCustomDelimiterNoEncodeArraySerialization() throws JsonProcessingException {
assertEquals(
"?paramA=first;second;third",
objectMapper.writeValueAsString(new CustomDelimiterNoEncodeArrayQuery(EXAMPLE_ARRAY)));
objectMapper.valueToTree(new CustomDelimiterNoEncodeArrayQuery(EXAMPLE_ARRAY)).textValue());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ private static class BoxedPropertyQuery {
@Test
public void testFalsePrimitivesSerialization() throws JsonProcessingException {
assertEquals(
"?paramB=false", objectMapper.writeValueAsString(new PrimitivePropertyQuery(false, false)));
"?paramB=false", objectMapper.valueToTree(new PrimitivePropertyQuery(false, false)).textValue());
}

@Test
public void testTruePrimitiveSerialization() throws JsonProcessingException {
assertEquals(
"?paramA&paramB=true",
objectMapper.writeValueAsString(new PrimitivePropertyQuery(true, true)));
objectMapper.valueToTree(new PrimitivePropertyQuery(true, true)).textValue());
}

@Test
Expand All @@ -80,19 +80,19 @@ public void testTruePrimitiveDeserialization() throws IOException {
@Test
public void testFalseBoxedSerialization() throws JsonProcessingException {
assertEquals(
"?paramB=false", objectMapper.writeValueAsString(new BoxedPropertyQuery(false, false)));
"?paramB=false", objectMapper.valueToTree(new BoxedPropertyQuery(false, false)).textValue());
}

@Test
public void testTrueBoxedSerialization() throws JsonProcessingException {
assertEquals(
"?paramA&paramB=true", objectMapper.writeValueAsString(new BoxedPropertyQuery(true, true)));
"?paramA&paramB=true", objectMapper.valueToTree(new BoxedPropertyQuery(true, true)).textValue());
}

@Test
public void testNullBoxedSerialization() throws JsonProcessingException {
assertEquals(
"?paramB=null", objectMapper.writeValueAsString(new BoxedPropertyQuery(null, null)));
"?paramB=null", objectMapper.valueToTree(new BoxedPropertyQuery(null, null)).textValue());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ private static class JsonFormatQuery {
public void testStringParamSerialization() throws JsonProcessingException {
assertEquals(
"?param=2013-01-31",
objectMapper.writeValueAsString(new JsonFormatQuery(LocalDate.parse("2013-01-31"))));
objectMapper.valueToTree(new JsonFormatQuery(LocalDate.parse("2013-01-31"))).textValue());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public void testStringParamSerialization() throws JsonProcessingException {
Calendar calendar = new GregorianCalendar(2013, 0, 31);
assertEquals(
"?param=2013-01-31",
objectMapper.writeValueAsString(new JsonFormatQuery(calendar.getTime())));
objectMapper.valueToTree(new JsonFormatQuery(calendar.getTime())).textValue());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ private static class MultiPropertyQuery {
public void testIgnoreParamSerialization() throws JsonProcessingException {
assertEquals(
"?paramA=valueA&paramC=123",
objectMapper.writeValueAsString(new MultiPropertyQuery("valueA", "valueB", 123)));
objectMapper.valueToTree(new MultiPropertyQuery("valueA", "valueB", 123)).textValue());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ private static class JsonPropertyQuery {
public void testNestedParamSerialization() throws JsonProcessingException {
// Not supported
assertThrows(
InvalidDefinitionException.class,
() -> objectMapper.writeValueAsString(new ObjectProperty("valueA", "valueB")));
IllegalArgumentException.class,
() -> objectMapper.valueToTree(new ObjectProperty("valueA", "valueB")).textValue());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public CustomDelimiterNoEncodeListQuery(List<String> values) {
public void testRegularListSerialization() throws JsonProcessingException {
assertEquals(
"?paramA=first&paramA=second&paramA=third",
objectMapper.writeValueAsString(new RegularListQuery(EXAMPLE_LIST)));
objectMapper.valueToTree(new RegularListQuery(EXAMPLE_LIST)).textValue());
}

@Test
Expand All @@ -116,7 +116,7 @@ public void testRegularListDeserialization() throws IOException {
public void testDelimitedListSerialization() throws JsonProcessingException {
assertEquals(
"?paramA=first%2Csecond%2Cthird",
objectMapper.writeValueAsString(new DelimitedListQuery(EXAMPLE_LIST)));
objectMapper.valueToTree(new DelimitedListQuery(EXAMPLE_LIST)).textValue());
}

@Test
Expand All @@ -130,7 +130,7 @@ public void testDelimitedListDeserialization() throws IOException {
public void testDelimitedListNoEncodeSerialization() throws JsonProcessingException {
assertEquals(
"?paramA=first,second,third",
objectMapper.writeValueAsString(new DelimitedListNoEncodeQuery(EXAMPLE_LIST)));
objectMapper.valueToTree(new DelimitedListNoEncodeQuery(EXAMPLE_LIST)).textValue());
}

@Test
Expand All @@ -144,7 +144,7 @@ public void testDelimitedListNoEncodeDeserialization() throws IOException {
public void testCustomDelimiterListSerialization() throws JsonProcessingException {
assertEquals(
"?paramA=first%3Bsecond%3Bthird",
objectMapper.writeValueAsString(new CustomDelimiterListQuery(EXAMPLE_LIST)));
objectMapper.valueToTree(new CustomDelimiterListQuery(EXAMPLE_LIST)).textValue());
}

@Test
Expand All @@ -159,7 +159,7 @@ public void testCustomDelimiterListDeserialization() throws IOException {
public void testCustomDelimiterNoEncodeListSerialization() throws JsonProcessingException {
assertEquals(
"?paramA=first;second;third",
objectMapper.writeValueAsString(new CustomDelimiterNoEncodeListQuery(EXAMPLE_LIST)));
objectMapper.valueToTree(new CustomDelimiterNoEncodeListQuery(EXAMPLE_LIST)).textValue());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public MultiPropertyQuery(String valueA, String valueB, int valueC) {
public void testMultiParamSerialization() throws JsonProcessingException {
assertEquals(
"?paramA=valueA&paramB=valueB&paramC=123",
objectMapper.writeValueAsString(new MultiPropertyQuery("valueA", "valueB", 123)));
objectMapper.valueToTree(new MultiPropertyQuery("valueA", "valueB", 123)).textValue());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ private static class MultiPropertyQuery {

@Test
public void testExcludedNullParamSerialization() throws JsonProcessingException {
assertEquals("?paramB=123", objectMapper.writeValueAsString(new MultiPropertyQuery(null, 123)));
assertEquals("?paramB=123", objectMapper.valueToTree(new MultiPropertyQuery(null, 123)).textValue());
}

@Test
public void testIncludedNullAsEmptyParamSerialization() throws JsonProcessingException {
assertEquals(
"?paramA=valueA&paramB=null",
objectMapper.writeValueAsString(new MultiPropertyQuery("valueA", null)));
objectMapper.valueToTree(new MultiPropertyQuery("valueA", null)).textValue());
}

@Test
Expand Down
Loading

0 comments on commit dd33157

Please sign in to comment.