2017-06-05 30 views
1

我嘗試使用@NotNull註釋,但它沒有奏效。如果JsonString中缺少任何字段,則會給出null(String)zero(int)。但是我想要的是如果在類中定義的JsonStr中缺少任何字段應該拋出異常。我的PojoClass可能有對象引用或多級對象引用。我正在使用GsonString轉換爲obj。 更多的澄清,我已經添加下面我的代碼:如何從JsonStr轉換爲PojoClassObj時拋出異常,如果在JsonStr中缺少任何鍵/值?

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"); 

      } 

對於現場輥,我用@NotNull引發異常如果該字段不存在在JsonStr但它給0值不引發任何異常。

我該如何實現?

請不要說這是重複的,因爲我已經看到這些問題:

回答

1

@NotNull不是GSON的一部分,它不能在默認情況下處理它(除非你加養活自己)。此外,可以將空性檢查註釋應用於基元字段 - 通常來說,這沒有多大意義。此外,默認int字段值爲0,並且Gson不檢查是否從JSON文檔讀取特定字段。然而,你可以很容易實現,如果你:

  • 稍微改變原始int其可空包裝Integer改變你的映射;
  • 實施自定義後處理驗證類型適配器。

例如,

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; 

} 

下一步是剛剛創建自己的類型的適配器檢查可空字段。

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

} 

測試(使用一些谷歌番石榴和自定義資源的讀者):

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

輸出:

反序列化文件與-roll.json
約翰·100
反序列化文件-without-roll.json
FAILED! com.google.gson.stream.MalformedJsonException:最後java.lang.Integer中q44362030.Person.roll沒有價值

同樣的,你可以創建你的另一TypeAdapter檢查所有領域的自動即使不需要@NotNull,但這需要更復雜的實現。

+0

您是否願意在main方法和immutableList的try塊中解釋一下「Q44362030.class」是什麼? 它給出了「getPackageResourceJsonReader」方法的錯誤。 – user404

+1

@ user404這只是一個自定義的資源讀取工廠方法,它允許從Q ###。類中聲明的包中讀取這兩個JSON資源。它的名稱源自您在S.O的問題ID。你可以很容易地用'新的JsonReader'來代替它並傳遞任何東西給它。 'ImmutableList'只是一個來自Google Guava的列表工廠方法,可以替換爲'asList'。簡而言之,我只是迭代了從您的問題中借用的資源JSON文檔來測試解決方案。 –

+0

感謝您的回覆。順便說一句,我試過這種方式,它仍然給出例外,雖然卷是存在於文件中。我的[鏈接](https://ideone.com/YNuMAM)。我幾乎迷失在這裏! – user404

0

你有沒有嘗試使用包裝類而不是原始的?

使用本:

@NotNull private Integer roll;

+0

我試過了。這只是排除了特定的領域,沒有例外。 – user404

相關問題