Java 特定字段的GSON整数到布尔值

Java 特定字段的GSON整数到布尔值,java,json,gson,Java,Json,Gson,我正在处理一个API,它返回整数(1=true,other=false)来表示布尔值 我已经看到了,但是我需要能够指定这应该应用于哪个字段,因为有时候整数实际上是整数 package com.company.product.json; import static com.company.product.Commands.*; import java.io.IOException; import java.util.logging.Logger; import com.google.gson

我正在处理一个API,它返回整数(1=true,other=false)来表示布尔值

我已经看到了,但是我需要能够指定这应该应用于哪个字段,因为有时候整数实际上是整数

package com.company.product.json;

import static com.company.product.Commands.*;

import java.io.IOException;
import java.util.logging.Logger;

import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import com.company.product.Commands;
import com.company.product.client.ClientSocket;

/**
 * Adapter for Command handling.
 * 
 * We write out the CommandName as an Integer, and read it in as a Commands constant.
 * 
 * This satisfies the requirement that the CommandName by represented by JSON as an int, but allows
 * us to deserialize it to a Commands object on read.
 * 
 * @author jdv
 * @see com.company.product.Command#commandName CommandName
 */
public class CommandsAdapter extends TypeAdapter<Commands> {

  private static final Logger logger = Logger.getLogger(ClientSocket.class.getPackage().getName());

  /*
   * (non-Javadoc) Deserialize the JSON "CommandName" integer into the corresponding Commands
   * constant object.
   * 
   * @see com.google.gson.TypeAdapter#read(com.google.gson.stream.JsonReader)
   */
  @Override
  public Commands read(JsonReader in) throws IOException {

    final int command;
    try {
      command = in.nextInt();

    } catch (IllegalStateException e) {
      logger.severe("Unable to read incoming JSON stream: " + e.getMessage());
      throw new IOException(e);

    } catch (NumberFormatException e) {
      logger
          .severe("Unable to read and convert CommandName Integer from the incoming JSON stream: "
              + e.getMessage());
      throw new IOException(e);
    }

    // Let's not risk using a bad array index. Not every command is expected
    // by the WebSocket handlers, but we should do our best to construct
    // a valid Commands object.
    if (command < NO_OP.getValue() || command > LAST_COMMAND.getValue()) {
      throw new IOException(new IllegalArgumentException(
          "Unexpected value encountered for Commands constant: " + command));
    } else {
      return Commands.values()[command];
    }
  }

  /*
   * (non-Javadoc) Serialize Commands object constants as their Integer values.
   * 
   * @see com.google.gson.TypeAdapter#write(com.google.gson.stream.JsonWriter, java.lang.Object)
   */
  @Override
  public void write(JsonWriter out, Commands value) throws IOException {
    out.value(value.getValue());
  }

}
编辑:传入的JSON可能如下所示(也可能是字符串而不是int,等等):


我需要一种方法来指定
int\u应该是布尔值的
应该被解析为布尔值,
regular\u int
应该被解析为整数。

如果我理解正确,您希望将传入JsonReader上的值从int规范化或转换为其他值,比如布尔值

package com.company.product.json;

import static com.company.product.Commands.*;

import java.io.IOException;
import java.util.logging.Logger;

import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import com.company.product.Commands;
import com.company.product.client.ClientSocket;

/**
 * Adapter for Command handling.
 * 
 * We write out the CommandName as an Integer, and read it in as a Commands constant.
 * 
 * This satisfies the requirement that the CommandName by represented by JSON as an int, but allows
 * us to deserialize it to a Commands object on read.
 * 
 * @author jdv
 * @see com.company.product.Command#commandName CommandName
 */
public class CommandsAdapter extends TypeAdapter<Commands> {

  private static final Logger logger = Logger.getLogger(ClientSocket.class.getPackage().getName());

  /*
   * (non-Javadoc) Deserialize the JSON "CommandName" integer into the corresponding Commands
   * constant object.
   * 
   * @see com.google.gson.TypeAdapter#read(com.google.gson.stream.JsonReader)
   */
  @Override
  public Commands read(JsonReader in) throws IOException {

    final int command;
    try {
      command = in.nextInt();

    } catch (IllegalStateException e) {
      logger.severe("Unable to read incoming JSON stream: " + e.getMessage());
      throw new IOException(e);

    } catch (NumberFormatException e) {
      logger
          .severe("Unable to read and convert CommandName Integer from the incoming JSON stream: "
              + e.getMessage());
      throw new IOException(e);
    }

    // Let's not risk using a bad array index. Not every command is expected
    // by the WebSocket handlers, but we should do our best to construct
    // a valid Commands object.
    if (command < NO_OP.getValue() || command > LAST_COMMAND.getValue()) {
      throw new IOException(new IllegalArgumentException(
          "Unexpected value encountered for Commands constant: " + command));
    } else {
      return Commands.values()[command];
    }
  }

  /*
   * (non-Javadoc) Serialize Commands object constants as their Integer values.
   * 
   * @see com.google.gson.TypeAdapter#write(com.google.gson.stream.JsonWriter, java.lang.Object)
   */
  @Override
  public void write(JsonWriter out, Commands value) throws IOException {
    out.value(value.getValue());
  }

}
如果是这样,您可能希望创建一个扩展TypeAdapter并重写read()的适配器类。从nextInt()获取值,然后根据其值返回相应的布尔值。根据解析器的配置,您可能必须检查空值

如果需要,可以重写同一适配器类中的write(),将客户端代码中的布尔值强制转换为JsonWriter的整数

[编辑]

作为参考,这里是我的TypeAdapter的一个示例,它将一个“Commands”枚举类强制转换为一个整数

package com.company.product.json;

import static com.company.product.Commands.*;

import java.io.IOException;
import java.util.logging.Logger;

import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import com.company.product.Commands;
import com.company.product.client.ClientSocket;

/**
 * Adapter for Command handling.
 * 
 * We write out the CommandName as an Integer, and read it in as a Commands constant.
 * 
 * This satisfies the requirement that the CommandName by represented by JSON as an int, but allows
 * us to deserialize it to a Commands object on read.
 * 
 * @author jdv
 * @see com.company.product.Command#commandName CommandName
 */
public class CommandsAdapter extends TypeAdapter<Commands> {

  private static final Logger logger = Logger.getLogger(ClientSocket.class.getPackage().getName());

  /*
   * (non-Javadoc) Deserialize the JSON "CommandName" integer into the corresponding Commands
   * constant object.
   * 
   * @see com.google.gson.TypeAdapter#read(com.google.gson.stream.JsonReader)
   */
  @Override
  public Commands read(JsonReader in) throws IOException {

    final int command;
    try {
      command = in.nextInt();

    } catch (IllegalStateException e) {
      logger.severe("Unable to read incoming JSON stream: " + e.getMessage());
      throw new IOException(e);

    } catch (NumberFormatException e) {
      logger
          .severe("Unable to read and convert CommandName Integer from the incoming JSON stream: "
              + e.getMessage());
      throw new IOException(e);
    }

    // Let's not risk using a bad array index. Not every command is expected
    // by the WebSocket handlers, but we should do our best to construct
    // a valid Commands object.
    if (command < NO_OP.getValue() || command > LAST_COMMAND.getValue()) {
      throw new IOException(new IllegalArgumentException(
          "Unexpected value encountered for Commands constant: " + command));
    } else {
      return Commands.values()[command];
    }
  }

  /*
   * (non-Javadoc) Serialize Commands object constants as their Integer values.
   * 
   * @see com.google.gson.TypeAdapter#write(com.google.gson.stream.JsonWriter, java.lang.Object)
   */
  @Override
  public void write(JsonWriter out, Commands value) throws IOException {
    out.value(value.getValue());
  }

}
package com.company.product.json;
导入静态com.company.product.Commands.*;
导入java.io.IOException;
导入java.util.logging.Logger;
导入com.google.gson.TypeAdapter;
导入com.google.gson.stream.JsonReader;
导入com.google.gson.stream.JsonWriter;
导入com.company.product.Commands;
导入com.company.product.client.ClientSocket;
/**
*用于命令处理的适配器。
* 
*我们将CommandName写成一个整数,并将其作为Commands常量读入。
* 
*这满足了CommandName由JSON表示为int的要求,但允许
*我们需要在读取时将其反序列化为Commands对象。
* 
*@author jdv
*@see com.company.product.Command#commandName commandName
*/
公共类CommandsAdapter扩展了TypeAdapter{
私有静态最终记录器Logger=Logger.getLogger(ClientSocket.class.getPackage().getName());
/*
*(非Javadoc)将JSON“CommandName”整数反序列化为相应的命令
*常量对象。
* 
*@see com.google.gson.TypeAdapter#read(com.google.gson.stream.JsonReader)
*/
@凌驾
公共命令read(JsonReader in)引发IOException{
最终int命令;
试一试{
command=in.nextInt();
}捕获(非法状态){
严重(“无法读取传入的JSON流:+e.getMessage());
抛出新的IOException(e);
}捕获(数字格式){
记录器
.severe(“无法从传入JSON流读取和转换CommandName Integer:”
+e.getMessage());
抛出新的IOException(e);
}
//我们不要冒险使用错误的数组索引。并非所有命令都是预期的
//通过WebSocket处理程序,但我们应该尽最大努力构建
//有效的命令对象。
if(commandLAST_command.getValue()){
抛出新IOException(新IllegalArgumentException(
命令常量遇到意外值:“+command”);
}否则{
返回Commands.values()[command];
}
}
/*
*(非Javadoc)将命令对象常量序列化为其整数值。
* 
*@see com.google.gson.TypeAdapter#write(com.google.gson.stream.JsonWriter,java.lang.Object)
*/
@凌驾
public void write(JsonWriter out,Commands value)抛出IOException{
out.value(value.getValue());
}
}

这实质上适应了“CommandName”序列化参数上的传入和传出操作,该参数在本地表示为“Commands”枚举,在远程表示为整数。与此命令枚举有关的任何内容都将通过覆盖read()和write()的适配器类进行筛选。最终,这会驱动WebSocket对等机,但对于本次讨论而言,这一切都无关紧要。HTH.

我们将为Gson提供一个小钩子,一个用于布尔值的自定义反序列化程序,即一个实现
JsonDeserializer
接口的类:

CustomBooleanTypeAdapter

import java.lang.reflect.Type;
import com.google.gson.*;
class BooleanTypeAdapter implements JsonDeserializer<Boolean> {
public Boolean deserialize(JsonElement json, Type typeOfT,
                           JsonDeserializationContext context) throws JsonParseException {
    if (((JsonPrimitive) json).isBoolean()) {
        return json.getAsBoolean();
    }
    if (((JsonPrimitive) json).isString()) {
        String jsonValue = json.getAsString();
        if (jsonValue.equalsIgnoreCase("true")) {
            return true;
        } else if (jsonValue.equalsIgnoreCase("false")) {
            return false;
        } else {
            return null;
        }
    }

    int code = json.getAsInt();
    return code == 0 ? false :
            code == 1 ? true : null;
  }
}
对于基元类型,请在1以下使用

 GsonBuilder builder = new GsonBuilder();
    builder.registerTypeAdapter(boolean.class, new BooleanTypeAdapter());
    Gson gson = builder.create();

享受
JSON
解析

假设有一些整数值我想作为布尔值处理,还有一些我想作为整数处理,正如我在问题的最后一句中所说的。如果它们来自JsonReader上的同一个序列化字段,则必须在read()中添加额外的逻辑来做出决定并返回正确的结果。但是,简而言之,如果您需要将传入或传出类型转换为其他类型,则需要为这些类型创建一个TypeAdapter类。我更新了问题以更清楚地解释问题。Gson非常面向类型。该名称用于序列化字段AFAIK,因此无法帮助您进行反序列化。您可能需要创建一个新的目标容器类型,将“1”强制为布尔值,或者可能需要创建自己的解析器,以便访问字段名。还有FieldAttributes,这可能是您在自定义反序列化程序上连接到fieldname的一种方式。谢谢!如果我理解正确,每当我试图用这个
BooleanTypeAdapter
集反序列化时,任何
boolean
都会被这样对待?@Maheshwar Ligade那么问题特定字段部分呢?此解决方案不适用于包含正常整数值的响应,如
quantity:0
此键不能表示为
Boolean
如果我的json中有一个正常的布尔字段以及由整数值表示的字段,它如何工作?这里的诀窍是Java类中的参数类型决定要使用哪个适配器使用。因此,如果
quantity
int
,它将使用标准整数适配器。如果
数量