Skip to content

Commit 534abb1

Browse files
committed
Fix #1605
1 parent d89cfa1 commit 534abb1

File tree

5 files changed

+94
-21
lines changed

5 files changed

+94
-21
lines changed

release-notes/CREDITS

+5
Original file line numberDiff line numberDiff line change
@@ -642,3 +642,8 @@ Harleen Sahni (harleensahni@github)
642642
* Reported #403: Make FAIL_ON_NULL_FOR_PRIMITIVES apply to primitive arrays and other
643643
types that wrap primitives
644644
(2.9.0)
645+
646+
Jared Jacobs (2is10@github)
647+
* Requested #1605: Allow serialization of `InetAddress` as simple numeric host address
648+
(2.9.0)
649+

release-notes/VERSION

+2
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ Project: jackson-databind
7474
#1554: Support deserialization of `Shape.OBJECT` ("as POJO") for `Map`s (and map-like types)
7575
#1556: Add `ObjectMapper.updateValue()` method to update instance with given overrides
7676
(suggested by syncer@github)
77+
#1605: Allow serialization of `InetAddress` as simple numeric host address
78+
(requested by Jared J)
7779

7880
2.8.9 (not yet released)
7981

src/main/java/com/fasterxml/jackson/databind/module/SimpleModule.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public class SimpleModule
3333

3434
protected final String _name;
3535
protected final Version _version;
36-
36+
3737
protected SimpleSerializers _serializers = null;
3838
protected SimpleDeserializers _deserializers = null;
3939

src/main/java/com/fasterxml/jackson/databind/ser/std/InetAddressSerializer.java

+64-12
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,90 @@
33
import java.io.IOException;
44
import java.net.InetAddress;
55

6+
import com.fasterxml.jackson.annotation.JsonFormat;
67
import com.fasterxml.jackson.core.*;
8+
import com.fasterxml.jackson.databind.BeanProperty;
9+
import com.fasterxml.jackson.databind.JsonMappingException;
10+
import com.fasterxml.jackson.databind.JsonSerializer;
711
import com.fasterxml.jackson.databind.SerializerProvider;
812
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
13+
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
914

1015
/**
1116
* Simple serializer for {@link java.net.InetAddress}. Main complexity is
1217
* with registration, since same serializer is to be used for sub-classes.
18+
*<p>
19+
* Since 2.9 allows use of {@link JsonFormat} configuration (annotation,
20+
* per-type defaulting) so that if <code>JsonFormat.Shape.NUMBER</code>
21+
* (or <code>ARRAY</code>) is used, will serialize as "host address"
22+
* (dotted numbers) instead of simple conversion.
1323
*/
1424
@SuppressWarnings("serial")
1525
public class InetAddressSerializer
1626
extends StdScalarSerializer<InetAddress>
27+
implements ContextualSerializer
1728
{
18-
public InetAddressSerializer() { super(InetAddress.class); }
29+
/**
30+
* @since 2.9
31+
*/
32+
protected final boolean _asNumeric;
1933

34+
public InetAddressSerializer() {
35+
this(false);
36+
}
37+
38+
/**
39+
* @since 2.9
40+
*/
41+
public InetAddressSerializer(boolean asNumeric) {
42+
super(InetAddress.class);
43+
_asNumeric = asNumeric;
44+
}
45+
2046
@Override
21-
public void serialize(InetAddress value, JsonGenerator jgen, SerializerProvider provider) throws IOException
47+
public JsonSerializer<?> createContextual(SerializerProvider serializers,
48+
BeanProperty property) throws JsonMappingException
2249
{
23-
// Ok: get textual description; choose "more specific" part
24-
String str = value.toString().trim();
25-
int ix = str.indexOf('/');
26-
if (ix >= 0) {
27-
if (ix == 0) { // missing host name; use address
28-
str = str.substring(1);
29-
} else { // otherwise use name
30-
str = str.substring(0, ix);
50+
JsonFormat.Value format = findFormatOverrides(serializers,
51+
property, handledType());
52+
boolean asNumeric = false;
53+
if (format != null) {
54+
JsonFormat.Shape shape = format.getShape();
55+
if (shape.isNumeric() || shape == JsonFormat.Shape.ARRAY) {
56+
asNumeric = true;
57+
}
58+
}
59+
if (asNumeric != _asNumeric) {
60+
return new InetAddressSerializer(asNumeric);
61+
}
62+
return this;
63+
}
64+
65+
@Override
66+
public void serialize(InetAddress value, JsonGenerator g, SerializerProvider provider) throws IOException
67+
{
68+
String str;
69+
70+
if (_asNumeric) { // since 2.9
71+
str = value.getHostAddress();
72+
} else {
73+
// Ok: get textual description; choose "more specific" part
74+
str = value.toString().trim();
75+
int ix = str.indexOf('/');
76+
if (ix >= 0) {
77+
if (ix == 0) { // missing host name; use address
78+
str = str.substring(1);
79+
} else { // otherwise use name
80+
str = str.substring(0, ix);
81+
}
3182
}
3283
}
33-
jgen.writeString(str);
84+
g.writeString(str);
3485
}
3586

3687
@Override
37-
public void serializeWithType(InetAddress value, JsonGenerator jgen, SerializerProvider provider, TypeSerializer typeSer) throws IOException, JsonGenerationException
88+
public void serializeWithType(InetAddress value, JsonGenerator jgen, SerializerProvider provider,
89+
TypeSerializer typeSer) throws IOException, JsonGenerationException
3890
{
3991
// Better ensure we don't use specific sub-classes...
4092
typeSer.writeTypePrefixForScalar(value, jgen, InetAddress.class);

src/test/java/com/fasterxml/jackson/databind/ser/jdk/TestJdkTypes.java renamed to src/test/java/com/fasterxml/jackson/databind/ser/jdk/JDKTypeSerializationTest.java

+22-8
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,25 @@
99
import java.util.*;
1010
import java.util.regex.Pattern;
1111

12+
import com.fasterxml.jackson.annotation.JsonFormat;
1213
import com.fasterxml.jackson.core.JsonGenerator;
1314
import com.fasterxml.jackson.databind.*;
1415

1516
/**
1617
* Unit tests for JDK types not covered by other tests (i.e. things
1718
* that are not Enums, Collections, Maps, or standard Date/Time types)
1819
*/
19-
public class TestJdkTypes
20+
public class JDKTypeSerializationTest
2021
extends com.fasterxml.jackson.databind.BaseMapTest
2122
{
2223
private final ObjectMapper MAPPER = objectMapper();
2324

25+
static class InetAddressBean {
26+
public InetAddress value;
27+
28+
public InetAddressBean(InetAddress i) { value = i; }
29+
}
30+
2431
public void testBigDecimal() throws Exception
2532
{
2633
Map<String, Object> map = new HashMap<String, Object>();
@@ -83,19 +90,26 @@ public void testLocale() throws IOException
8390
public void testInetAddress() throws IOException
8491
{
8592
assertEquals(quote("127.0.0.1"), MAPPER.writeValueAsString(InetAddress.getByName("127.0.0.1")));
86-
assertEquals(quote("google.com"), MAPPER.writeValueAsString(InetAddress.getByName("google.com")));
93+
InetAddress input = InetAddress.getByName("google.com");
94+
assertEquals(quote("google.com"), MAPPER.writeValueAsString(input));
95+
96+
ObjectMapper mapper = new ObjectMapper();
97+
mapper.configOverride(InetAddress.class)
98+
.setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.NUMBER));
99+
String json = mapper.writeValueAsString(input);
100+
assertEquals(quote(input.getHostAddress()), json);
101+
102+
assertEquals(String.format("{\"value\":\"%s\"}", input.getHostAddress()),
103+
mapper.writeValueAsString(new InetAddressBean(input)));
87104
}
88105

89106
public void testInetSocketAddress() throws IOException
90107
{
91-
assertEquals(
92-
quote("127.0.0.1:8080"),
108+
assertEquals(quote("127.0.0.1:8080"),
93109
MAPPER.writeValueAsString(new InetSocketAddress("127.0.0.1", 8080)));
94-
assertEquals(
95-
quote("google.com:6667"),
110+
assertEquals(quote("google.com:6667"),
96111
MAPPER.writeValueAsString(new InetSocketAddress("google.com", 6667)));
97-
assertEquals(
98-
quote("[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443"),
112+
assertEquals(quote("[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443"),
99113
MAPPER.writeValueAsString(new InetSocketAddress("2001:db8:85a3:8d3:1319:8a2e:370:7348", 443)));
100114
}
101115

0 commit comments

Comments
 (0)