[tor-commits] [exonerator/master] Replace Gson with Jackson.

karsten at torproject.org karsten at torproject.org
Wed May 30 13:35:55 UTC 2018


commit e15c3a64610c04b2db3dcbbd8f7f7890c9a3101e
Author: Karsten Loesing <karsten.loesing at gmx.net>
Date:   Tue May 22 20:58:18 2018 +0200

    Replace Gson with Jackson.
    
    Implements #26163.
---
 CHANGELOG.md                                       |  3 ++
 build.xml                                          |  6 ++-
 .../metrics/exonerator/QueryResponse.java          | 47 +++++++++-------------
 .../metrics/exonerator/QueryResponseTest.java      |  5 ++-
 4 files changed, 30 insertions(+), 31 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6b80bf4..9766439 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,8 @@
 # Changes in version 2.0.3 - 2018-0?-??
 
+ * Medium changes
+   - Replace Gson with Jackson.
+
  * Minor changes
    - Remove duplicate [] surrounding suggested IPv6 addresses.
 
diff --git a/build.xml b/build.xml
index b82ce0a..b0fced5 100644
--- a/build.xml
+++ b/build.xml
@@ -9,7 +9,7 @@
   <property name="javadoc-title" value="ExoneraTor API Documentation"/>
   <property name="implementation-title" value="ExoneraTor" />
   <property name="release.version" value="2.0.2-dev" />
-  <property name="metricslibversion" value="2.1.1" />
+  <property name="metricslibversion" value="2.4.0" />
   <property name="jetty.version" value="-9.2.21.v20170120" />
   <property name="warfile"
             value="exonerator-${release.version}.war"/>
@@ -34,7 +34,9 @@
   <patternset id="common" >
     <include name="commons-codec-1.10.jar"/>
     <include name="commons-lang3-3.5.jar"/>
-    <include name="gson-2.4.jar" />
+    <include name="jackson-annotations-2.8.6.jar"/>
+    <include name="jackson-core-2.8.6.jar"/>
+    <include name="jackson-databind-2.8.6.jar"/>
     <include name="logback-core-1.1.9.jar" />
     <include name="logback-classic-1.1.9.jar" />
     <include name="postgresql-9.4.1212.jar"/>
diff --git a/src/main/java/org/torproject/metrics/exonerator/QueryResponse.java b/src/main/java/org/torproject/metrics/exonerator/QueryResponse.java
index 96e32cc..6a77565 100644
--- a/src/main/java/org/torproject/metrics/exonerator/QueryResponse.java
+++ b/src/main/java/org/torproject/metrics/exonerator/QueryResponse.java
@@ -3,68 +3,60 @@
 
 package org.torproject.metrics.exonerator;
 
-import com.google.gson.Gson;
-import com.google.gson.annotations.Expose;
-import com.google.gson.annotations.SerializedName;
-
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.PropertyNamingStrategy;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.IOException;
 import java.io.Reader;
 
 /** Query response from the ExoneraTor database. */
 public class QueryResponse {
 
-  @Expose(serialize = false, deserialize = false)
   private static Logger logger = LoggerFactory.getLogger(QueryResponse.class);
 
   /* Actual version implemented by this class. */
-  @Expose(serialize = false, deserialize = false)
   private static final String VERSION = "1.0";
 
   /* Don't accept query responses with versions lower than this. */
-  @Expose(serialize = false, deserialize = false)
   private static final String FIRSTRECOGNIZEDVERSION = "1.0";
 
   /* Don't accept query responses with this version or higher. */
-  @Expose(serialize = false, deserialize = false)
   private static final String FIRSTUNRECOGNIZEDVERSION = "2.0";
 
+  private static ObjectMapper objectMapper = new ObjectMapper()
+      .setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)
+      .setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
+      .setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE)
+      .setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
+
   /** Version of this response format. */
-  @Expose
   String version = VERSION;
 
   /** Query IP address passed in the request; never <code>null</code>. */
-  @Expose
-  @SerializedName("query_address")
   String queryAddress;
 
   /** Query date passed in the request; never <code>null</code>. */
-  @Expose
-  @SerializedName("query_date")
   String queryDate;
 
   /** ISO-formatted valid-after time of the first status contained in the
    * database; only <code>null</code> if the database is empty. */
-  @Expose
-  @SerializedName("first_date_in_database")
   String firstDateInDatabase;
 
   /** ISO-formatted valid-after time of the last status contained in the
    * database; only <code>null</code> if the database is empty. */
-  @Expose
-  @SerializedName("last_date_in_database")
   String lastDateInDatabase;
 
   /** Whether there is at least one relevant status in the database on or within
    * a day of the requested date; <code>null</code> if the database is empty. */
-  @Expose
-  @SerializedName("relevant_statuses")
   Boolean relevantStatuses;
 
   /** All matches for the given IP address and date; <code>null</code> if there
    * were no matches at all. */
-  @Expose
   Match[] matches;
 
   /** Constructor for Gson. */
@@ -85,16 +77,16 @@ public class QueryResponse {
   }
 
   /** Return JSON string for given QueryResponse. */
-  public static String toJson(QueryResponse response) {
-    return new Gson().toJson(response);
+  public static String toJson(QueryResponse response) throws IOException {
+    return objectMapper.writeValueAsString(response);
   }
 
   /** Return QueryResponse parsed from the given input stream, or
    * {@code null} if something fails or an unrecognized version is found. */
   public static QueryResponse fromJson(Reader reader) {
-    Gson gson = new Gson();
     try {
-      QueryResponse response = gson.fromJson(reader, QueryResponse.class);
+      QueryResponse response = objectMapper.readValue(reader,
+          QueryResponse.class);
       if (null == response || null == response.version) {
         logger.warn("Response is either empty or does not contain "
             + "version information.");
@@ -107,7 +99,10 @@ public class QueryResponse {
         return null;
       }
       return response;
-    } catch (RuntimeException e) {
+    } catch (IOException | RuntimeException e) {
+      /* We're catching RuntimeException here, rather than IOException, so that
+       * we return null if anything goes wrong, including cases that we did not
+       * anticipate. */
       logger.error("JSON decoding failed.", e);
     }
     return null;
@@ -148,8 +143,6 @@ public class QueryResponse {
 
   /** All known IP addresses in the same /24 or /48 network; <code>null</code>
    * if there were direct matches for the given IP address. */
-  @Expose
-  @SerializedName("nearby_addresses")
   String[] nearbyAddresses;
 }
 
diff --git a/src/test/java/org/torproject/metrics/exonerator/QueryResponseTest.java b/src/test/java/org/torproject/metrics/exonerator/QueryResponseTest.java
index d188f15..5390340 100644
--- a/src/test/java/org/torproject/metrics/exonerator/QueryResponseTest.java
+++ b/src/test/java/org/torproject/metrics/exonerator/QueryResponseTest.java
@@ -11,6 +11,7 @@ import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameters;
 
+import java.io.IOException;
 import java.io.StringReader;
 import java.util.Arrays;
 import java.util.Collection;
@@ -103,7 +104,7 @@ public class QueryResponseTest {
   }
 
   @Test
-  public void testJsonReading() {
+  public void testJsonReading() throws IOException {
     if (null == this.queryResponse) {
       assertNull(QueryResponse.fromJson(new StringReader(this.json)));
     } else {
@@ -113,7 +114,7 @@ public class QueryResponseTest {
   }
 
   @Test
-  public void testJsonWriting() {
+  public void testJsonWriting() throws IOException {
     if (null == this.queryResponse) {
       return;
     }





More information about the tor-commits mailing list