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

2022-09-03 04:43:07

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

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

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

{ 
    "regular_int": 1234, 
    "int_that_should_be_a_boolean": 1
}

我需要一种方法来指定应解析为布尔值,并应解析为整数。int_that_should_be_a_booleanregular_int


答案 1

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

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;
  }
}

要使用它,我们需要稍微改变一下获取映射器实例的方式,使用工厂对象GsonBuilder,一种常见的模式使用方式在这里。GsonGSON

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

对于基元类型,请使用低于 1

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

享受解析!JSON


答案 2

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

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

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

[编辑]

作为参考,这是我的TypeAdapter的一个例子,它将“命令”枚举类强制为/来自整数。

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());
  }

}

这实质上是调整“CommandName”序列化参数上的传入和传出操作,该参数在本地表示为“命令”枚举和远程整数。与此命令枚举相关的任何内容都通过此适配器类进行筛选,该适配器类将覆盖 read() 和 write()。最终,这推动了WebSocket对等节点,但对于本文的讨论而言,这些都无关紧要。呵呵。