2017-05-25 1 views
1

クラスには正しいClassTypeAdapterを書きましたが、クラスをフィールドとして含むオブジェクトを処理しようとすると失敗します。GsonがUnsupportedOperationExceptionをスローするとjava.lang.Classをフィールドとして文字列に変換しようとしました

添付の問題を再現する実行可能なメインメソッドを持つClassTypeAdapter。

アイデア?

import com.google.gson.Gson; 
    import com.google.gson.GsonBuilder; 
    import com.google.gson.TypeAdapter; 
    import com.google.gson.stream.JsonReader; 
    import com.google.gson.stream.JsonWriter; 

    import java.io.IOException; 

    public class ClassTypeAdapter extends TypeAdapter<Class<?>> { 
     private static final String PARAM_NAME = "className"; 

     @Override 
     public void write(JsonWriter out, Class<?> value) throws IOException { 
      out.beginObject(); 

      out.name(PARAM_NAME).value(value.getName()); 

      out.endObject(); 
     } 

     @Override 
     public Class<?> read(JsonReader in) throws IOException { 
      Class<?> readClass = null; 

      in.beginObject(); 

      while (in.hasNext()) { 
       if (PARAM_NAME.equals(in.nextName())) { 
        try { 
         readClass = Class.forName(in.nextString()); 
        } catch (ClassNotFoundException e) { 
         throw new IOException("Class not found", e); 
        } 
       } 
      } 

      in.endObject(); 

      return readClass; 
     } 

     public static class TestClass<T> { 
      private Class<T> aClass; 
     } 

     public static void main(String[] args) { 
      final Gson gson = new GsonBuilder().registerTypeAdapter(Class.class, new ClassTypeAdapter()).create(); 

      final TestClass testClass = new TestClass<>(); 

      System.out.println(gson.toJson(testClass)); // {} 
      System.out.println(gson.toJson(Object.class)); // {"className":"java.lang.Object"} 

      testClass.aClass = Object.class; 

      System.out.println(gson.toJson(testClass)); // UnsupportedOperationException 
     } 
    } 

エラーのスタックトレース:

Exception in thread "main" java.lang.UnsupportedOperationException: Attempted to serialize java.lang.Class: java.lang.Object. Forgot to register a type adapter? 
    at com.google.gson.internal.bind.TypeAdapters$1.write(TypeAdapters.java:76) 
    at com.google.gson.internal.bind.TypeAdapters$1.write(TypeAdapters.java:69) 
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:125) 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:243) 
    at com.google.gson.Gson.toJson(Gson.java:669) 
    at com.google.gson.Gson.toJson(Gson.java:648) 
    at com.google.gson.Gson.toJson(Gson.java:603) 
    at com.google.gson.Gson.toJson(Gson.java:583) 
    at ClassTypeAdapter.main(ClassTypeAdapter.java:56) 

答えて

1

私は解決策hereを見つけました。

public class ClassTypeAdapter implements JsonSerializer<Class<?>>, JsonDeserializer<Class<?>> { 
    @Override 
    public JsonElement serialize(Class<?> src, Type typeOfSrc, JsonSerializationContext context) { 
     return new JsonPrimitive(src.getName()); 
    } 

    @Override 
    public Class<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
     try { 
      return Class.forName(json.getAsString()); 
     } catch (ClassNotFoundException e) { 
      throw new JsonParseException(e); 
     } 
    } 
} 

JUnitテスト:

import com.google.gson.Gson; 
import com.google.gson.GsonBuilder; 
import org.junit.Test; 

import static org.junit.Assert.assertEquals; 

public class ClassTypeAdapterTest { 
    @Test 
    public void testReadWrite() { 
     final Class<?> classToWrite = ClassTypeAdapter.class; 

     final Gson gson = new GsonBuilder().registerTypeAdapter(Class.class, new ClassTypeAdapter()).create(); 

     final String writtenClass = gson.toJson(classToWrite); 
     final Class readClass = gson.fromJson(writtenClass, Class.class); 

     assertEquals(classToWrite, readClass); 
    } 

    @Test 
    public void testInnerClassProblem() { 
     final Gson gson = new GsonBuilder().registerTypeAdapter(Class.class, new ClassTypeAdapter()).create(); 

     final TestClass testClass = new TestClass<>(); 
     testClass.innerClass = Object.class; 

     final String writtenClass = gson.toJson(testClass); 
     final TestClass readClass = gson.fromJson(writtenClass, TestClass.class); 

     assertEquals(testClass.innerClass, readClass.innerClass); 
    } 

    private static class TestClass<T> { 
     private Class<T> innerClass; 
    } 
} 
関連する問題