通过Google Cloud Endpoints转移BigDecimal的例外情况

时间:2015-02-26 11:39:11

标签: java android google-app-engine google-cloud-endpoints

我试图通过云端点传输文章数据,遗留应用程序(Android)使用的数据结构要求所有价格都在BigDecimal中。这是我的实体类:

import org.hibernate.annotations.GenericGenerator;

import java.math.BigDecimal;

import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;


@Entity
@Table(name = "articles")
public class Article {
    private int id;
    ....
    private BigDecimal price;


    @Id
    @Column(name = "_id")
    @GeneratedValue(generator="increment")
    @GenericGenerator(name="increment", strategy = "increment")
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    .....

    @Basic
    @Column(name = "price", precision=7, scale=2)
    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }
}

使用API​​资源管理器,我得到以下结果:

{
 "items": [
  {
   "id": 2,
   ....
   "price": 5.00001,
   ...
  }
}

尝试使用此代码在Android中使用端点时:

String accountName = intent.getStringExtra(EXTRA_CREDENTIALS);
GoogleAccountCredential credentials = GoogleAccountCredential.usingAudience(this,
        AppConstants.AUDIENCE);
credentials.setSelectedAccountName(accountName);
if(articleApiService == null) {  // Only do this once
    articleApiService = AppConstants.getApiServiceHandle(credentials);
}

CollectionResponseArticle articles = null;
try {
    articles = articleApiService.listArticles().execute();
} catch (Exception e) {
    Log.e(TAG, e.getMessage());
}

我在JSONParser.java中遇到以下异常:

java.lang.IllegalArgumentException: key price
        at com.google.api.client.json.JsonParser.parseValue(JsonParser.java:880)
        ...
 Caused by: java.lang.IllegalArgumentException: key price, field private java.util.List com.example.articlesendpoint.model.CollectionResponseArticle.items
        at com.google.api.client.json.JsonParser.parseValue(JsonParser.java:880)
        ...
 Caused by: java.lang.IllegalArgumentException: key price, field private java.util.List com.example.articlesendpoint.model.CollectionResponseArticle.items
        at com.google.api.client.json.JsonParser.parseValue(JsonParser.java:880)
        ...
 Caused by: java.lang.IllegalArgumentException: key price, field private com.example.articlesendpoint.model.BigDecimal com.example.articlesendpoint.model.Article.price
        at com.google.api.client.json.JsonParser.parseValue(JsonParser.java:880)
        ...
 Caused by: java.lang.IllegalArgumentException: expected numeric type but got class com.example.articlesendpoint.model.BigDecimal
        at com.google.api.client.json.JsonParser.parseValue(JsonParser.java:843)
            at com.google.api.client.json.JsonParser.parse(JsonParser.java:471)
            at com.google.api.client.json.JsonParser.parseValue(JsonParser.java:780)
            at com.google.api.client.json.JsonParser.parseArray(JsonParser.java:647)
            at com.google.api.client.json.JsonParser.parseValue(JsonParser.java:739)
            at com.google.api.client.json.JsonParser.parse(JsonParser.java:471)
            at com.google.api.client.json.JsonParser.parseValue(JsonParser.java:780)
            at com.google.api.client.json.JsonParser.parse(JsonParser.java:381)
            at com.google.api.client.json.JsonParser.parse(JsonParser.java:354)
            at com.google.api.client.json.JsonObjectParser.parseAndClose(JsonObjectParser.java:87)
            at com.google.api.client.json.JsonObjectParser.parseAndClose(JsonObjectParser.java:81)
            at com.google.api.client.http.HttpResponse.parseAs(HttpResponse.java:459)
            at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:460)
            at com.pos.android.dbsync.DBsyncService.onHandleIntent(DBsyncService.java:57)
            at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.os.HandlerThread.run(HandlerThread.java:61)

检查生成的端点客户端库时,有一个BigDecimal 对我来说自动生成的模型类似乎无法识别android JSON反序列化器:

/*
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
/*
 * This code was generated by https://code.google.com/p/google-apis-client-generator/
 * (build: 2015-01-14 17:53:03 UTC)
 * on 2015-02-25 at 19:50:44 UTC 
 * Modify at your own risk.
 */

package com.example.articlesendpoint.model;

/**
 * Model definition for BigDecimal.
 *
 * <p> This is the Java data model class that specifies how to parse/serialize into the JSON that is
 * transmitted over HTTP when working with the articlesendpoint. For a detailed explanation see:
 * <a href="http://code.google.com/p/google-http-java-client/wiki/JSON">http://code.google.com/p/google-http-java-client/wiki/JSON</a>
 * </p>
 *
 * @author Google, Inc.
 */
@SuppressWarnings("javadoc")
public final class BigDecimal extends com.google.api.client.json.GenericJson {

  /**
   * The value may be {@code null}.
   */
  @com.google.api.client.util.Key
  private java.lang.Integer scale;

  /**
   * @return value or {@code null} for none
   */
  public java.lang.Integer getScale() {
    return scale;
  }

  /**
   * @param scale scale or {@code null} for none
   */
  public BigDecimal setScale(java.lang.Integer scale) {
    this.scale = scale;
    return this;
  }

  @Override
  public BigDecimal set(String fieldName, Object value) {
    return (BigDecimal) super.set(fieldName, value);
  }

  @Override
  public BigDecimal clone() {
    return (BigDecimal) super.clone();
  }

}

知道我在这里做错了什么吗?

1 个答案:

答案 0 :(得分:1)

BigDecimal不是受支持的返回类型。 The supported return types are

java.lang.String
java.lang.Boolean and boolean
java.lang.Integer and int
java.lang.Long and long
java.lang.Float and float
java.lang.Double and double
java.util.Date
com.google.api.server.spi.types.DateAndTime
com.google.api.server.spi.types.SimpleDate
Any enum
Any array or java.util.Collection of a parameter type

您有几个选择:

  1. 使用@ApiTranformer - 在文章中的变换器传递中返回一个包装的Article实体,该实体代表价格值,如String

  2. 忘记变换器的东西,只需装饰你的模型,并确保你的端点方法返回装饰类型,如

  3. public WrappedArticle(Article article) {
        price = article.getPrice().toString();
        ....
    }
    
    1. 使用@JsonIgnore注释 价格 ,以便杰克逊反序列化程序(假设您使用默认的json工厂)忽略该属性,并添加另一个属性比如说String类型。确保使用 @IgnoreSave 进行注释,以便Objectify不会将其存储为您实体的一部分。
    2. @IgnoreSave
      private String priceStr;
      

      现在您可以提供以下getter:

      public String getPriceStr() {
        return price.toString();
      }
      

      就是这样。完成工作!