通过 Google 云端点传输 BigDecimal 时出现异常
Exception on transfering BigDecimal over Google Cloud Endpoints
我正在尝试通过云端点传输文章数据,而旧版应用程序 (Android) 使用的数据结构要求所有价格都采用 BigDecimal。这是我的实体 class:
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
为我自动生成的模型 class 似乎无法被 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();
}
}
知道我做错了什么吗?
BigDecimal 不是受支持的 return 类型。 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
您有几个选择:
使用 @ApiTranformer - 在您的转换器中传递一个 Article 和 return 一个包装的 Article 实体,它表示价格值,如 String
忘掉转换器的东西,只装饰你的模型并确保你的端点方法return是装饰类型,比如
public WrappedArticle(Article article) {
price = article.getPrice().toString();
....
}
- 用 @JsonIgnore 注释 price 以便 Jackson 反序列化器(假设您使用的是默认值 json factory) 忽略 属性,并添加另一个 属性 类型的字符串。确保使用 @IgnoreSave 进行注释,以便 Objectify 不会将其存储为实体的一部分。
@IgnoreSave
private String priceStr;
现在您可以提供以下内容 getter:
public String getPriceStr() {
return price.toString();
}
就是这样。任务完成!
我正在尝试通过云端点传输文章数据,而旧版应用程序 (Android) 使用的数据结构要求所有价格都采用 BigDecimal。这是我的实体 class:
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 为我自动生成的模型 class 似乎无法被 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();
}
}
知道我做错了什么吗?
BigDecimal 不是受支持的 return 类型。 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
您有几个选择:
使用 @ApiTranformer - 在您的转换器中传递一个 Article 和 return 一个包装的 Article 实体,它表示价格值,如 String
忘掉转换器的东西,只装饰你的模型并确保你的端点方法return是装饰类型,比如
public WrappedArticle(Article article) {
price = article.getPrice().toString();
....
}
- 用 @JsonIgnore 注释 price 以便 Jackson 反序列化器(假设您使用的是默认值 json factory) 忽略 属性,并添加另一个 属性 类型的字符串。确保使用 @IgnoreSave 进行注释,以便 Objectify 不会将其存储为实体的一部分。
@IgnoreSave
private String priceStr;
现在您可以提供以下内容 getter:
public String getPriceStr() {
return price.toString();
}
就是这样。任务完成!