[英]Java Android Gson convert boolean to int from response server
伙计们,帮帮我! 请提出一个简单的解决方案,将Android中的boolean类型从服务器转换为int :)当我登录时,我会像这样从服务器得到响应:
{"status":{"error":0,"code":200,"message":"OK"},"response":{"profile":{"id":114,"username":"k@gmail.com","full_name":"k","phone":"9999999","verified":1,"admin":0,"allow_dev":false,"company":{"id":9,"name":"ООО \"Фингерз медиа\"","email":"info@fingers.by","sample":null,"logo":"http://storage.guardian-glass.fingersmedia.by/0cb56968b3cec1bba301db8d51d1015e.jpg"}},"access_token":"15629e234e04a54a5a44ef2aa4eccb1d"}}
然后我得到undefined exception: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected NUMBER but was BOOLEAN
发生这种情况是因为JsonElement“ allow_dev ”是来自服务器的布尔值 ,并且在Android中,我具有像int这样的“ allow_dev ”。
这是登录方法:
private void login(String email, String pass) {
showProgress();
JsonObject params = new JsonObject();
params.addProperty("username", email);
params.addProperty("password", pass);
UserOperationsTask task = new UserOperationsTask(UserOperationsTask.TaskMode.MODE_LOGIN, params) {
@Override
public void onLoadFinished(Bundle res) {
hideProgress();
String errorMessage = res.getString(UserOperationsTask.RESULT_ERROR_STRING);
if (errorMessage != null) {
showMessage(getString(R.string.login_error), getString(R.string.server_request_error));
} else {
String json = res.getString(UserOperationsTask.RESULT_JSON_STRING);
if (json != null) {
JsonParser parser = new JsonParser();
JsonObject responseData = parser.parse(json).getAsJsonObject();
JsonObject companyObj = responseData.getAsJsonObject("profile").getAsJsonObject("company");
}
setRegisteredMode();
}
}
};
task.execute(this);
}
此方法解析响应,我试图将allow_dev类型从boolean转换为int,但是我不明白我是否做得对?
private Bundle parseProfileResponse(Context context, JsonObject responseData) {
Log.d(TAG, "parseProfileResponse");
// I tried convert allow_dev type from boolean to int
String allow_dev_server = String.valueOf(responseData.get("allow_dev"));
boolean b = allow_dev_server.equals("true");
int allow_dev = b ? 1 : 0; // true == 1
Profile profile;
profile = GsonHolder.getGSONInstance().fromJson(responseData.getAsJsonObject("profile"), Profile.class);
profile.allow_dev = allow_dev;
Bundle res = new Bundle();
res.putParcelable(RESULT_OBJ, profile);
res.putString(RESULT_JSON_STRING, responseData.toString());
try {
Cache.saveToCache(context, profile);
} catch (RemoteException e) {
Log.d(TAG, "parseAuthResponse RemoteException: " + e.toString());
res.putString(RESULT_ERROR_STRING, context.getString(R.string.database_error));
} catch (OperationApplicationException e) {
Log.d(TAG, "parseAuthResponse OperationApplicationException: " + e.toString());
res.putString(RESULT_ERROR_STRING, context.getString(R.string.database_error));
}
return res;
}
我必须获取“ allow_dev ”,将其转换为int并写入数据库。
如果您可以切换到映射,则可以使用静态类型所提供的所有功能,与弱“类型化”的JsonElement
及其子类进行比较。 它具有几个优点:编译时检查,更健壮的代码,IDE支持等。主要缺点是您必须编写自定义映射,但是那里的工具(以及在线工具)可以尝试根据以下内容生成简单的映射类:给定的示例JSON(例如,此处的一种非常流行的工具: http : //www.jsonschema2pojo.org/ )。
现在,让我们创建一些映射。 如下所示的映射很少使用: final
字段(用于“服务器响应”,不应通过编程方式进行修改; Gson始终可以分配此类字段); 非基元为null
,某些基元类型的默认值会欺骗编译器(例如Integer.value(0)
而不是简单的0
:否则, javac
可能内联常量,因此Gson不会影响它们); 没有吸气剂/吸气剂(数据传输对象只是数据包,但是的,吸气剂可以更好地工作)。 无论如何,您都可以使用自己的样式,并且以下映射用于演示目的(映射代码甚至具有紧凑的格式:每行一个属性折叠注释)。
final class Response<T> {
final Status status = null;
final T response = null;
}
final class Status {
final int error = Integer.valueOf(0);
final int code = Integer.valueOf(0);
final String message = null;
}
final class ProfileAndAccessToken {
final Profile profile = null;
@SerializedName("access_token") final String accessToken = null;
}
final class Profile {
final int id = Integer.valueOf(0);
final String username = null;
@SerializedName("full_name") final String fullName = null;
final String phone = null;
final int verified = Integer.valueOf(0);
final int admin = Integer.valueOf(0);
@SerializedName("allow_dev") @JsonAdapter(BooleanToIntTypeAdapter.class) final int allowDev = Integer.valueOf(0);
final Company company = null;
}
final class Company {
final int id = Integer.valueOf(0);
final String name = null;
final String email = null;
final String sample = null;
final URL logo = null;
}
请注意上面的两个注释:
@SerializedName
-此注释可以“重命名”字段,因此您甚至可以使用特殊字符(但是不建议使用,通常用于将传入的JSON属性名称映射到javaCamelNamingConventions)。 @JsonAdapter
-此批注可以将特殊类型的适配器“附加”到某个字段,以便可以将JSON属性转换为给定的字段,反之亦然。 现在,让我们实现一个类型适配器,该适配器可以将传入的boolean
值转换为本地int
值,反之亦然。 请注意,类型适配器以流方式工作,因此您必须在读取期间动态读取JSON令牌流,并且当然必须在写入期间生成JSON令牌流。
final class BooleanToIntTypeAdapter
extends TypeAdapter<Integer> {
// Public constructors may be evil, and let expose as less as possible
// Gson can still instantiate this type adapter itself
private BooleanToIntTypeAdapter() {
}
@Override
@SuppressWarnings("resource")
public void write(final JsonWriter out, final Integer value)
throws IOException {
// If the given value is null, we must write the `null` token to the output JSON tokens stream anyway in order not to break JSON documents
if ( value == null ) {
out.nullValue();
return;
}
// Let's assume that we can accept either 0 or 1 that are mapped to false and true respectively
switch ( value ) {
case 0:
out.value(false);
break;
case 1:
out.value(true);
break;
default:
// Or throw an exception as fast as we can
throw new IllegalArgumentException("Cannot convert " + value + " to a boolean literal");
}
}
@Override
public Integer read(final JsonReader in)
throws IOException {
// Peek the next token type, and if it's null, then return null value too
if ( in.peek() == NULL ) {
return null;
}
// Otherwise parse the next token as boolean and map it either to 1 or 0
return in.nextBoolean() ? 1 : 0;
}
}
这就是Gson您所需要的。 现在,对于整个JSON,由于响应映射类是通用的,因此您必须告诉Gson T
是什么。 Gson在fromJson
方法中接受java.lang.reflect.Type
,并且此类型可以同时包含原始和参数化类型,因此Gson可以更准确地进行(反)序列化。
private static final Type profileAndAccessTokenResponse = new TypeToken<Response<ProfileAndAccessToken>>() {
}.getType();
final Response<ProfileAndAccessToken> response = gson.fromJson(JSON, profileAndAccessTokenResponse);
System.out.println(response.response.profile.allowDev);
System.out.println(gson.toJson(response, profileAndAccessTokenResponse));
输出:
0
{ “状态”:{ “错误”:0 “代码”:200, “消息”: “OK”}, “响应”:{ “轮廓”:{ “ID”:114, “用户名”:“K @ gmail.com”, “FULL_NAME”: “K”, “手机”: “9999999”, “验证”:1, “管理员”:0, “allow_dev”:假的, “公司”:{ “ID”:9, “名称”:“ООО\\”Фингерзмедиа\\“”,“电子邮件”:“ info@fingers.by”,“徽标”:“ http://storage.guardian-glass.fingersmedia.by/0cb56968b3cec1bba301db8d51d1015e.jpg ” } “的access_token”: “15629e234e04a54a5a44ef2aa4eccb1d”}}
请注意,第一行是0
:这是使用BooleanToIntTypeAdapter
生成的。 返回您的代码:
String allow_dev_server = String.valueOf(responseData.get("allow_dev"));
boolean b = allow_dev_server.equals("true");
int allow_dev = b ? 1 : 0; // true == 1
Profile profile;
profile = GsonHolder.getGSONInstance().fromJson(responseData.getAsJsonObject("profile"), Profile.class);
profile.allow_dev = allow_dev;
可以替换为简单的:
final Profile profile = GsonHolder.getGSONInstance().fromJson(responseData.getAsJsonObject("profile"), Profile.class)
// now `Profile.allowDev` is 0 or 1 automatically
请注意, responseData
可以替换为特定的映射,因此您甚至无法在那一行进行解析:可能您可以将整个response
对象简单地传递为类映射,而不是parseProfileResponse
中的JsonObject
parseProfileResponse
-这样会更健壮。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.