使用gson解析输入有效负载时如何忽略类型不匹配

raogr8fs  于 2023-10-18  发布在  其他
关注(0)|答案(1)|浏览(131)

类别:

public class Site 
{

    @JsonProperty("id")
    String id;

    @JsonProperty("name")
    String name;

    @SerializedName("switch_mgmt")
    Map<String, Object> switchMgmt;

}

String = "{" +
        " \"switch_mgmt\": \"\",\"id\": \"16fc48fa-5a5f-4b0b-882c-5347ef5e3969\"
        "}";

这里我尝试使用gson以如下方式解析上面的字符串:

Site data = gson.fromJson(jsonString, new Site().getClass());

但我总是得到一个例外:

[redis] get /internal/sites redis exception: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 18 path $.switch_mgmt

我知道有一个类型不匹配,这就是为什么它正在寻找开始_OBJECT,但遇到了一个String。这个有效载荷是由用户通过 Postman API设置的,我无法控制用户给出的输入。
有没有一种方法可以让gson忽略这种类型不匹配?
switch_mgmt的示例(理想):

"switch_mgmt": {
    "proxy": false,
    "port": "2222",
    "root_password": "abc"
},
m2xkgtsf

m2xkgtsf1#

这可以通过自定义TypeAdapterFactory来解决,它获取字段类型的默认适配器,但 Package 它并首先检查JSON数据以检测无效值,例如您的示例中的空字符串。举例来说:

class SwitchMgmtAdapterFactory implements TypeAdapterFactory {
    // Constructor called by Gson using reflection
    public SwitchMgmtAdapterFactory() {
    }

    @Override
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
        // Obtain the default adapter for the type of the field
        // Uses getAdapter instead of getDelegateAdapter due to https://github.com/google/gson/issues/1028
        TypeAdapter<T> delegate = gson.getAdapter(type);

        return new TypeAdapter<T>() {
            @Override
            public T read(JsonReader in) throws IOException {
                if (in.peek() == JsonToken.BEGIN_OBJECT) {
                    return delegate.read(in);
                }

                // Otherwise handle malformed value
                // In this example here the value is skipped and `null` is returned,
                // but could instead also inspect the JSON value and use it in some way
                in.skipValue();
                return null;
            }

            @Override
            public void write(JsonWriter out, T value) throws IOException {
                delegate.write(out, value);
            }
        };
    }
}

然后,您可以使用@JsonAdapter在现场注册该适配器工厂:

public class Site 
{
    @JsonAdapter(SwitchMgmtAdapterFactory.class)
    @SerializedName("switch_mgmt")
    Map<String, Object> switchMgmt;

    ...
}

然而,正如在评论中提到的,我个人认为要求客户提供有效数据会更好。这使您更容易维护代码,也使客户端更容易注意到它们发送的数据格式不正确。否则,他们可能会浪费时间试图理解为什么他们提供的价值被忽略。虽然也注意到Gson目前是does not detect unknown fieldsmissing fields

相关问题