GSON解析器的麻烦

时间:2017-05-16 12:16:06

标签: java json gson

我有一个json,它是解析器SearchAnalyticsQueryRequest to String

的结果
val request = new SearchAnalyticsQueryRequest()
  request.setStartDate("2017-05-09")
  request.setEndDate("2017-05-16")
  request.setDimensions(List("page", "query").asJava)
  request.setRowLimit(5000)
  request.setStartRow(0)

val gson = new GsonBuilder().create()
val result = gson.toJson(request)

结果是:

{"dimensions":["page","query"],"endDate":"2017-05-16","rowLimit":5000,"startDate":"2017-05-09","startRow":0}

当我试图向后做时

val backResult = gson.fromJson(result, classOf[SearchAnalyticsQueryRequest])

我有一个例外:

java.lang.IllegalArgumentException: Can not set java.lang.Integer field com.google.api.services.webmasters.model.SearchAnalyticsQueryRequest.rowLimit to java.lang.Double
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
at java.lang.reflect.Field.set(Field.java:764)
at com.google.api.client.util.FieldInfo.setFieldValue(FieldInfo.java:245)
at com.google.api.client.util.FieldInfo.setValue(FieldInfo.java:206)
at com.google.api.client.util.GenericData.put(GenericData.java:103)
at com.google.api.client.util.GenericData.put(GenericData.java:47)
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:188)
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:145)
at com.google.gson.Gson.fromJson(Gson.java:887)
at com.google.gson.Gson.fromJson(Gson.java:852)
at com.google.gson.Gson.fromJson(Gson.java:801)
at com.google.gson.Gson.fromJson(Gson.java:773)

如果我从json字符串中删除rowLimit和startRow - 正确解析了SearchAnalyticsQueryRequest

我需要做什么才能将所有json字符串解析为SearchAnalyticsQueryRequest

已解决

val json = {"site":"<some url>","request":{"startDate":"2017-05-09","endDate":"2017-05-16","rowLimit":5000,"startRow":0,"dimensions":["query","page"],"dimensionFilterGroups":[{"filters":[{"dimension":"page","expression":"<some url>"}]}]}}

case class WebmastersRequest(site: String, request: SearchAnalyticsQueryRequest)

def fromGoogleJsonToSearchAnalytics(json: String): (Option[WebmastersRequest], Option[String]) = {
  val gson: Gson = new GsonBuilder().create()
  Try {
    val builder = new GsonBuilder()
    builder.registerTypeHierarchyAdapter(classOf[SearchAnalyticsQueryRequest], new JsonDeserializer[SearchAnalyticsQueryRequest]() {
      override def deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): SearchAnalyticsQueryRequest = {
        val jo = json.getAsJsonObject
        val req = new SearchAnalyticsQueryRequest()
        req.setAggregationType(Option(jo.get("aggregationType")).map(_.getAsString).orNull)
        req.setDimensionFilterGroups(Option(jo.get("dimensionFilterGroups")).map(o => gson.fromJson(o.getAsJsonArray, classOf[java.util.List[ApiDimensionFilterGroup]])).orNull)
        req.setDimensions(Option(jo.get("dimensions")).map(o => gson.fromJson(o.getAsJsonArray, classOf[java.util.List[String]])).orNull)
        req.setEndDate(Option(jo.get("endDate")).map(_.getAsString).orNull)
        req.setRowLimit(Option(jo.get("rowLimit")).map(i => Integer.valueOf(i.getAsInt)).orNull)
        req.setSearchType(Option(jo.get("searchType")).map(_.getAsString).orNull)
        req.setStartDate(Option(jo.get("startDate")).map(_.getAsString).orNull)
        req.setStartRow(Option(jo.get("startRow")).map(i => Integer.valueOf(i.getAsInt)).orNull)
        req
      }
    })

    builder.create().fromJson(json, classOf[WebmastersRequest])

  } match {
    case Success(x) => (Option(x), None)
    case Failure(e) =>
      e.printStackTrace()
      (None, Option(e.getMessage))
  }
}

这个有效! 如果有人告诉我如何删除

val gson: Gson = new GsonBuilder().create()

我将不胜感激:)

1 个答案:

答案 0 :(得分:4)

JSON不区分整数和浮点字段,这就是为什么在将JSON字符串反序列化为GSON时,数字字段将被视为Double,并且您将收到错误

  

无法设置java.lang.Integer字段   com.google.api.services.webmasters.model.SearchAnalyticsQueryRequest.rowLimit   到java.lang.Double

您可以使用adapter按照此答案将Double解析为整数: https://stackoverflow.com/a/20524187/2611451

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Double.class,  new JsonSerializer<Double>() {

    public JsonElement serialize(Double src, Type typeOfSrc,
                JsonSerializationContext context) {
            Integer value = (int)Math.round(src);
            return new JsonPrimitive(value);
        }
    });

Gson gs = gsonBuilder.create();