PageRenderTime 98ms CodeModel.GetById 31ms RepoModel.GetById 3ms app.codeStats 0ms

/json/src/test/java/io/airlift/json/TestJsonModule.java

https://gitlab.com/github-cloud-corp/airlift
Java | 389 lines | 308 code | 57 blank | 24 comment | 31 complexity | 99ed3bb063d89e590317cf5b14da3531 MD5 | raw file
  1. /*
  2. * Copyright 2010 Proofpoint, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package io.airlift.json;
  17. import com.fasterxml.jackson.annotation.JsonProperty;
  18. import com.fasterxml.jackson.core.JsonParser;
  19. import com.fasterxml.jackson.core.JsonToken;
  20. import com.fasterxml.jackson.core.type.TypeReference;
  21. import com.fasterxml.jackson.databind.DeserializationContext;
  22. import com.fasterxml.jackson.databind.ObjectMapper;
  23. import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
  24. import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
  25. import com.google.common.base.Joiner;
  26. import com.google.common.base.Splitter;
  27. import com.google.common.collect.ImmutableList;
  28. import com.google.common.collect.ImmutableSet;
  29. import com.google.common.collect.Maps;
  30. import com.google.inject.Binder;
  31. import com.google.inject.Guice;
  32. import com.google.inject.Injector;
  33. import com.google.inject.Module;
  34. import org.joda.time.DateTime;
  35. import org.joda.time.format.ISODateTimeFormat;
  36. import org.testng.annotations.BeforeMethod;
  37. import org.testng.annotations.Test;
  38. import java.io.IOException;
  39. import java.util.List;
  40. import java.util.Map;
  41. import static com.google.common.base.MoreObjects.toStringHelper;
  42. import static io.airlift.json.JsonBinder.jsonBinder;
  43. import static org.joda.time.DateTimeZone.UTC;
  44. import static org.testng.Assert.assertEquals;
  45. public class TestJsonModule
  46. {
  47. public static final Car CAR = new Car()
  48. .setMake("BMW")
  49. .setModel("M3")
  50. .setYear(2011)
  51. .setPurchased(new DateTime().withZone(UTC))
  52. .setNotes("sweet!")
  53. .setNameList(superDuper("d*a*i*n"));
  54. private ObjectMapper objectMapper;
  55. @BeforeMethod
  56. public void setUp()
  57. throws Exception
  58. {
  59. Injector injector = Guice.createInjector(new JsonModule(),
  60. new Module()
  61. {
  62. @Override
  63. public void configure(Binder binder)
  64. {
  65. jsonBinder(binder).addSerializerBinding(SuperDuperNameList.class).toInstance(ToStringSerializer.instance);
  66. jsonBinder(binder).addDeserializerBinding(SuperDuperNameList.class).to(SuperDuperNameListDeserializer.class);
  67. }
  68. });
  69. objectMapper = injector.getInstance(ObjectMapper.class);
  70. }
  71. @Test
  72. public void testJsonCodecFactoryBinding()
  73. throws Exception
  74. {
  75. Injector injector = Guice.createInjector(new JsonModule());
  76. JsonCodecFactory codecFactory = injector.getInstance(JsonCodecFactory.class);
  77. Person.validatePersonJsonCodec(codecFactory.jsonCodec(Person.class));
  78. Person.validatePersonListJsonCodec(codecFactory.listJsonCodec(Person.class));
  79. Person.validatePersonMapJsonCodec(codecFactory.mapJsonCodec(String.class, Person.class));
  80. }
  81. @Test
  82. public void testSetup()
  83. throws Exception
  84. {
  85. assertEquals(CAR, CAR);
  86. String json = objectMapper.writeValueAsString(CAR);
  87. Car actual = objectMapper.readValue(json, Car.class);
  88. assertEquals(actual, CAR);
  89. }
  90. @Test
  91. public void testFieldDetection()
  92. throws Exception
  93. {
  94. Map<String, Object> actual = objectMapper.readValue(objectMapper.writeValueAsString(CAR), Map.class);
  95. // notes is not annotated so should not be included
  96. // color is null so should not be included
  97. assertEquals(actual.keySet(), ImmutableSet.of("make", "model", "year", "purchased", "nameList"));
  98. }
  99. @Test
  100. public void testDateTimeRendered()
  101. throws Exception
  102. {
  103. Map<String, Object> actual = objectMapper.readValue(objectMapper.writeValueAsString(CAR), Map.class);
  104. assertEquals(actual.get("purchased"), ISODateTimeFormat.dateTime().print(CAR.getPurchased()));
  105. }
  106. @Test
  107. public void testGuavaRoundTrip()
  108. throws Exception
  109. {
  110. ImmutableList<Integer> list = ImmutableList.of(3, 5, 8);
  111. String json = objectMapper.writeValueAsString(list);
  112. ImmutableList<Integer> actual = objectMapper.readValue(json, new TypeReference<ImmutableList<Integer>>() {});
  113. assertEquals(actual, list);
  114. }
  115. @Test
  116. public void testIgnoreUnknownFields()
  117. throws Exception
  118. {
  119. Map<String, Object> data = Maps.newHashMap(objectMapper.readValue(objectMapper.writeValueAsString(CAR), Map.class));
  120. // add an unknown field
  121. data.put("unknown", "bogus");
  122. // Jackson should deserialize the object correctly with the extra unknown data
  123. assertEquals(objectMapper.readValue(objectMapper.writeValueAsString(data), Car.class), CAR);
  124. }
  125. public static class Car
  126. {
  127. // These fields are public to make sure that Jackson is ignoring them
  128. public String make;
  129. public String model;
  130. public int year;
  131. public DateTime purchased;
  132. // property that will be null to verify that null fields are not rendered
  133. public String color;
  134. // non-json property to verify that auto-detection is disabled
  135. public String notes;
  136. // property that requires special serializer and deserializer
  137. public SuperDuperNameList nameList;
  138. @JsonProperty
  139. public String getMake()
  140. {
  141. return make;
  142. }
  143. @JsonProperty
  144. public Car setMake(String make)
  145. {
  146. this.make = make;
  147. return this;
  148. }
  149. @JsonProperty
  150. public String getModel()
  151. {
  152. return model;
  153. }
  154. @JsonProperty
  155. public Car setModel(String model)
  156. {
  157. this.model = model;
  158. return this;
  159. }
  160. @JsonProperty
  161. public int getYear()
  162. {
  163. return year;
  164. }
  165. @JsonProperty
  166. public Car setYear(int year)
  167. {
  168. this.year = year;
  169. return this;
  170. }
  171. @JsonProperty
  172. public DateTime getPurchased()
  173. {
  174. return purchased;
  175. }
  176. @JsonProperty
  177. public Car setPurchased(DateTime purchased)
  178. {
  179. this.purchased = purchased;
  180. return this;
  181. }
  182. @JsonProperty
  183. public String getColor()
  184. {
  185. return color;
  186. }
  187. @JsonProperty
  188. public Car setColor(String color)
  189. {
  190. this.color = color;
  191. return this;
  192. }
  193. @JsonProperty
  194. public SuperDuperNameList getNameList()
  195. {
  196. return nameList;
  197. }
  198. @JsonProperty
  199. public Car setNameList(SuperDuperNameList nameList)
  200. {
  201. this.nameList = nameList;
  202. return this;
  203. }
  204. // this field should not be written
  205. public String getNotes()
  206. {
  207. return notes;
  208. }
  209. public Car setNotes(String notes)
  210. {
  211. this.notes = notes;
  212. return this;
  213. }
  214. @Override
  215. public boolean equals(Object o)
  216. {
  217. if (this == o) {
  218. return true;
  219. }
  220. if (!(o instanceof Car)) {
  221. return false;
  222. }
  223. Car car = (Car) o;
  224. if (year != car.year) {
  225. return false;
  226. }
  227. if (color != null ? !color.equals(car.color) : car.color != null) {
  228. return false;
  229. }
  230. if (make != null ? !make.equals(car.make) : car.make != null) {
  231. return false;
  232. }
  233. if (model != null ? !model.equals(car.model) : car.model != null) {
  234. return false;
  235. }
  236. if (nameList != null ? !nameList.equals(car.nameList) : car.nameList != null) {
  237. return false;
  238. }
  239. if (purchased != null ? !purchased.equals(car.purchased) : car.purchased != null) {
  240. return false;
  241. }
  242. return true;
  243. }
  244. @Override
  245. public int hashCode()
  246. {
  247. int result = make != null ? make.hashCode() : 0;
  248. result = 31 * result + (model != null ? model.hashCode() : 0);
  249. result = 31 * result + year;
  250. result = 31 * result + (purchased != null ? purchased.hashCode() : 0);
  251. result = 31 * result + (color != null ? color.hashCode() : 0);
  252. result = 31 * result + (nameList != null ? nameList.hashCode() : 0);
  253. return result;
  254. }
  255. @Override
  256. public String toString()
  257. {
  258. return toStringHelper(this)
  259. .add("make", make)
  260. .add("model", model)
  261. .add("year", year)
  262. .add("purchased", purchased)
  263. .add("color", color)
  264. .add("notes", notes)
  265. .add("nameList", nameList)
  266. .toString();
  267. }
  268. }
  269. public static class SuperDuperNameList
  270. {
  271. private List<String> name;
  272. private SuperDuperNameList(String superDuperNameList)
  273. {
  274. this(superDuperNameList, null);
  275. }
  276. private SuperDuperNameList(String superDuperNameList, Object stopJacksonFromUsingStringConstructor)
  277. {
  278. this.name = ImmutableList.copyOf(Splitter.on('*').split(superDuperNameList));
  279. }
  280. public List<String> getName()
  281. {
  282. return name;
  283. }
  284. @Override
  285. public String toString()
  286. {
  287. return Joiner.on("*").join(name);
  288. }
  289. @Override
  290. public boolean equals(Object o)
  291. {
  292. if (this == o) {
  293. return true;
  294. }
  295. if (!(o instanceof SuperDuperNameList)) {
  296. return false;
  297. }
  298. SuperDuperNameList that = (SuperDuperNameList) o;
  299. if (!name.equals(that.name)) {
  300. return false;
  301. }
  302. return true;
  303. }
  304. @Override
  305. public int hashCode()
  306. {
  307. return name.hashCode();
  308. }
  309. }
  310. public final static class SuperDuperNameListDeserializer
  311. extends StdScalarDeserializer<SuperDuperNameList>
  312. {
  313. public SuperDuperNameListDeserializer()
  314. {
  315. super(SuperDuperNameList.class);
  316. }
  317. @Override
  318. public SuperDuperNameList deserialize(JsonParser jp, DeserializationContext context)
  319. throws IOException
  320. {
  321. JsonToken token = jp.getCurrentToken();
  322. if (token == JsonToken.VALUE_STRING) {
  323. return new SuperDuperNameList(jp.getText(), null);
  324. }
  325. throw context.mappingException(getValueClass());
  326. }
  327. }
  328. public static SuperDuperNameList superDuper(String superDuperNameList)
  329. {
  330. return new SuperDuperNameList(superDuperNameList, null);
  331. }
  332. }