如果JsonStr中缺少任何键/值,如何在从JsonStr转换为PojoClassObj时引发异常? [英] How to throw exception while converting from JsonStr to PojoClassObj if any key/value is missing in the JsonStr?

查看:65
本文介绍了如果JsonStr中缺少任何键/值,如何在从JsonStr转换为PojoClassObj时引发异常?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用@NotNull批注,但是没有用.如果JsonString中缺少任何字段,则给出null(String)zero(int).但是我想要的是,如果在类中定义的JsonStr中缺少任何字段,则应该引发异常.

I tried using @NotNull annotation but it did not work. If any field is missing in the JsonString, it gives null(String) or zero(int). But what I want is if any field is missing in the JsonStr defined in the class should throw an exception.

添加:我的PojoClass可能具有对象引用或多级对象引用.我正在使用 Gson String转换为obj. 为了进一步说明,我在下面添加了我的代码:

Add: My PojoClass may have object reference or multilevel object reference. I am using Gson for the conversion of the String to obj. for more clarification, I have added my code below:

JsonStr:

{
   "name":"John",
   "id":1,
   "roll":100,
   "c":{
      "city":"Dhaka",
      "school":"B. govt. School"
   }
}

代码:

public class C {

    private String city;
    private String school;

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getSchool() {
        return school;
    }

    public void setSchool(String school) {
        this.school = school;
    }

}

ClassB:

public class B {

    private String name;
    private int id;
    @NotNull
    private int roll;
    private C c;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getRoll() {
        return roll;
    }

    public void setRoll(int roll) {
        this.roll = roll;
    }

    public C getC() {
        return c;
    }

    public void setC(C c) {
        this.c = c;
    }

}

MainClass:

try {
                B obj = new B();
                String str = "{\"name\":\"John\",\"id\":1,\"c\":{\"city\":\"dhaka\",\"school\":\"school\"}}";
                obj = gson.fromJson(str, B.class);

            } catch (RuntimeException e) {
                 System.out.println("exception Message");

            }

对于字段滚动,如果JsonStr中不存在该字段,则我使用@NotNull引发异常,但该字段给出0的值而不会引发任何异常.

For the field roll, I used @NotNull to throw an exception if that field is not present in the JsonStr but it gives 0 value without throwing any exception.

我该如何实现?

请不要说这是重复的,因为我已经看过以下问题:

Please don't say this is duplicate, because I have seen these questions:

  • 什么是NullPointerException,如何解决它?

    What is a NullPointerException, and how do I fix it?

    推荐答案

    @NotNull不是Gson的一部分,并且默认情况下它无法处理它(除非您自己添加支持).同样,可空性检查注释不应应用于原始字段,通常来说,这没有多大意义.另外,默认的int字段值为0,并且Gson不会检查是否从JSON文档中读取了特定的字段.但是,如果您满足以下条件,则可以轻松实现它:

    @NotNull is not a part of Gson, and it cannot handle it by default (unless you add support yourself). Also, nullability-check annotations should not be applied to primitives fields -- generally speaking it makes not much sense. Also, the default int fields values are 0, and Gson does not check if a particular field was read from a JSON document. However, you can easily implement it if you:

    • 通过将原语int更改为其可为空的包装器Integer;
    • 来稍微更改您的映射
    • 实现自定义的后处理验证类型适配器.
    • slightly change your mapping by changing the primitive int to its nullable wrapper Integer;
    • implement a custom post-processing validation type adapter.

    例如,

    final class Person {
    
        final String name = null;
    
        final int id = Integer.valueOf(0); // final primitive fields are inlined by javac
    
        @NotNull
        final Integer roll = null;
    
        @SerializedName("c")
        final Location location = null;
    
    }
    

    final class Location {
    
        final String city = null;
    
        final String school = null;
    
    }
    

    下一步就是创建您自己的类型适配器以检查可为空的字段.

    The next step is just creating your own type adapter to check the nullable fields.

    final class NotNullTypeAdapterFactory
            implements TypeAdapterFactory {
    
        // The type adapter factory holds no state, so no need to instantiate it multiple times
        private static final TypeAdapterFactory notNullTypeAdapterFactory = new NotNullTypeAdapterFactory();
    
        private NotNullTypeAdapterFactory() {
        }
    
        static TypeAdapterFactory getNotNullTypeAdapterFactory() {
            return notNullTypeAdapterFactory;
        }
    
        @Override
        public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
            final Collection<Field> notNullFields = getNotNullFields(typeToken.getRawType());
            // If no @NotNull fields found, then just tell Gson to pick the next best type adapter
            if ( notNullFields.isEmpty() ) {
                return null;
            }
            // If there's at least one @NotNull field, get the original type adapter
            final TypeAdapter<T> delegateTypeAdapter = gson.getDelegateAdapter(this, typeToken);
            return new TypeAdapter<T>() {
                @Override
                public void write(final JsonWriter out, final T value)
                        throws IOException {
                    delegateTypeAdapter.write(out, value);
                }
    
                @Override
                public T read(final JsonReader in)
                        throws IOException {
                    try {
                        // Read the value ...
                        final T value = delegateTypeAdapter.read(in);
                        // ... and make some post-processing
                        for ( final Field f : notNullFields ) {
                            if ( f.get(value) == null ) {
                                throw new MalformedJsonException(f + " has no value");
                            }
                        }
                        return value;
                    } catch ( final IllegalAccessException ex ) {
                        throw new IOException(ex);
                    }
                }
            };
        }
    
        private static Collection<Field> getNotNullFields(final Class<?> clazz) {
            // Primitive types and java.lang.Object do not have @NotNull
            if ( clazz.isPrimitive() || clazz == Object.class ) {
                return emptyList();
            }
            // Scan the whole hierarchy from the bottom subclass to the top superclass (except java.lang.Object we mentioned above)
            final Collection<Field> notNullFields = new ArrayList<>();
            for ( Class<?> c = clazz; c != Object.class; c = c.getSuperclass() ) {
                for ( final Field f : c.getDeclaredFields() ) {
                    if ( f.isAnnotationPresent(NotNull.class) ) {
                        // Don't forget to make private fields accessible
                        f.setAccessible(true);
                        notNullFields.add(f);
                    }
                }
            }
            return notNullFields;
        }
    
    }
    

    测试(使用一些Google Guava和自定义资源阅读器):

    Test (uses some Google Guava and custom resource readers):

    private static final Gson gson = new GsonBuilder()
            .registerTypeAdapterFactory(getNotNullTypeAdapterFactory())
            .create();
    
    public static void main(final String... args)
            throws IOException {
        for ( final String resourceName : ImmutableList.of("file-with-roll.json", "file-without-roll.json") ) {
            System.out.println("Deserializing " + resourceName);
            try ( final JsonReader jsonReader = getPackageResourceJsonReader(Q44362030.class, resourceName) ) {
                try {
                    final Person person = gson.fromJson(jsonReader, Person.class);
                    System.out.println(person.name + " " + person.roll);
                } catch ( final Exception ex ) {
                    System.out.println("FAILED! " + ex.getMessage());
                }
            }
        }
    }
    

    输出:

    反序列化file-with-roll.json
    约翰100
    反序列化file-without-roll.json
    失败的! com.google.gson.stream.MalformedJsonException:最终java.lang.Integer q44362030.Person.roll没有值

    Deserializing file-with-roll.json
    John 100
    Deserializing file-without-roll.json
    FAILED! com.google.gson.stream.MalformedJsonException: final java.lang.Integer q44362030.Person.roll has no value

    类似地,您可以创建另一个TypeAdapter来自动检查所有字段,甚至不需要@NotNull,但这需要更复杂的实现.

    Similarly, you can create your another TypeAdapter to check all fields automatically not even needing @NotNull, but this needs a more complicated implementation.

    这篇关于如果JsonStr中缺少任何键/值,如何在从JsonStr转换为PojoClassObj时引发异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆