2015-06-26 5 views
0

У меня есть класс для хранения некоторых данных JSON следующим образом:Gson Класс отбрасывать исключение

package org.swx.nursing.tools.configuration.data; 

import java.util.Set; 

import com.cerner.system.exception.Verifier; 
import com.cerner.system.exception.VerifyException; 
import com.google.common.collect.ImmutableSet; 

/** 
* Class representing a simple {@link JsonData#identifier}, 
* {@link JsonData#data} format. This class can be used to 
* persist application data for example in a Configuration file. 
* 
* @author SW029693 
* @since v1.0 
*/ 
public class JsonData <T>{ 
/** 
* Represents a unique identifier 
*/ 
private String identifier; 
/** 
* Represents the data pertaining to this {@link JsonData#identifier} 
*/ 
private T data; 

private static final Set<String> VALID_JSON_ID_TYPES = ImmutableSet.of("CONFIG","HOTKEYS"); 

public JsonData(String identifier, T data) { 
    super(); 
    this.identifier = identifier; 
    this.data = data; 
} 

/** 
* Getter for {@link JsonData#identifier} 
* @return 
*/ 
public String getIdentifier() { 
    return identifier; 
} 

/** 
* Sets the {@link JsonData#identifier} to the given value 
* @param identifier 
*   Represents a unique {@link JsonData#identifier} 
* @throws VerifyException 
*   If the argument is {@code null} or {@code empty} 
*/ 
public void setIdentifier(String identifier) throws VerifyException{ 
    Verifier.verifyNotNull(identifier, "identifier : null"); 
    Verifier.verifyNotEmpty(identifier,"identifier : empty"); 
    this.identifier = identifier; 
} 

/** 
* Getter for {@link JsonData} 
* @return 
*/ 
public T getData() { 
    return data; 
} 

/** 
* Sets the {@link JsonData#data} to the given value 
* @param identifier 
*   Represents a unique {@link JsonData#data} 
* @throws VerifyException 
*   If the argument is {@code null} 
*/ 
public void setData(T data) { 
    Verifier.verifyNotNull(data, "data : null"); 
    this.data = data; 
} 

@Override 
public String toString() { 
    return "JsonData [identifier=" + identifier + ", data=" + data + "]"; 
} 
} 

Я пытаюсь преобразовать некоторые данные в формате JSON (записать его в файл), прочитать его обратно и ввергнут в над объектом JsonData. Это мой блок тест, который не удается:

@Test 
@SuppressWarnings("unchecked") 
public void testWriteContentsToFile() { 
    ConfigurationManager<JsonData> configurationManager = (ConfigurationManager<JsonData>) 
    ConfigurationManager.Factory.create(); 
    assertNotNull(configurationManager); 
    configurationManager.write(getMockJsonData()); 
    System.out.println("1="+getMockJsonData().getData().toString()); 

    assertEquals(getMockJsonData().getData(), ((JsonData) readconfigFile()).getData()); 
} 

The вспомогательных методов для этого теста следующим образом:

/** 
* Helper method to read the config.json file 
* @return 
*/ 
private static JsonData<ConfigurationProperty> readconfigFile() { 
    Reader reader = null; 
    JsonData<ConfigurationProperty> data = null; 
    Gson gson = null; 
    try { 
     reader = new FileReader("./config.json"); 
     gson = new GsonBuilder().create(); 
     data = gson.fromJson(reader, JsonData.class); 
     System.out.println("yooo="+data.getData().getRunnableContext()); 
    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
     fail("Test failed while reading the config.json file: "+e.getMessage());  } 
    finally { 
     try { 
      reader.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      fail("Test failed while reading the config.json file: "+e.getMessage()); 
     } 
    } 
    return data; 
} 

и

/** 
* Helper method which creates a mock {@link JsonData} object for testing purposes 
* 
* @return An instance of the newly created mock {@link Jsondata} object 
*/ 
private static JsonData<ConfigurationProperty> getMockJsonData() { 
    JsonData<ConfigurationProperty> data = new JsonData<ConfigurationProperty>("CONFIG", 
      getMockConfigurationProperty("testKey", "testContext", "APPLICATION")); 
    System.out.println("data ==="+data); 
    return data; 
} 

/** 
* Helper method which creates a {@link ConfigurationProperty} based on the given 
* non-null and non-empty arguments. This method can be used to get the 
* {@link ConfigurationProperty} instance created with the desired fields when ALL 
* of the 3 parameters are non-null, non-empty & valid. 
* 
* @param mockHotKey 
*   A non-null & non-empty mockHotkey parameter passed in as an argument 
* 
* @param mockContext 
*   A non-null & non-empty mockContext parameter passed in as an argument 
* 
* @param mockContextType 
*   A non-null & non-empty mockContextType parameter passed in as an argument 
*   
* @throws VerifierException 
*   If the argument validation for non-null or non-empty arguments as failed. 
* 
* @throws IllegalArgumentException 
*   The {@link ConfigurationProperty.Builder#withRunnableContextType(String type) method 
*   throws an {@link IllegalArgumentException} if the provided type is not supported in 
*   {@link ConfigurationProperty#RUNNABLE_CONTEXT_TYPE} 
*   
* @return An instance of newly created {@link ConfigurationProperty} object 
*/ 
private static ConfigurationProperty getMockConfigurationProperty (
     String mockHotKey, String mockContext, String mockContextType) { 
    Verifier.verifyNotNull(mockHotKey); 
    Verifier.verifyNotNull(mockContext); 
    Verifier.verifyNotNull(mockContextType); 
    Verifier.verifyNotEmpty(mockHotKey); 
    Verifier.verifyNotEmpty(mockContext); 
    Verifier.verifyNotEmpty(mockContextType); 
    return ConfigurationProperty.Builder 
       .create() 
       .withHotKey(mockHotKey) 
       .withRunnableContext(mockContext) 
       .withRunnableContextType(mockContextType) 
       .build(); 
} 

Я получаю следующее сообщение об ошибке при запуске чтобы прочитать данные из json-файла в мой объект JsonData:

java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to org.swx.nursing.tools.configuration.data.ConfigurationProperty 
at org.swx.nursing.tools.configuration.data.ConfigurationManagerImplTest.readconfigFile(ConfigurationManagerImplTest.java:181) 
at org.swx.nursing.tools.configuration.data.ConfigurationManagerImplTest.testWriteContentsToFile(ConfigurationManagerImplTest.java:166) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
at java.lang.reflect.Method.invoke(Method.java:597) 
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66) 
at org.jmock.integration.junit4.JMock$1.invoke(JMock.java:37) 
at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:105) 
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:86) 
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:94) 
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:84) 
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49) 
at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:98) 
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:61) 
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:54) 
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34) 
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44) 
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:52) 
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49) 
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 

Файл будет записан так:

{ 
"identifier": "CONFIG", 
"data": { 
    "hotKey": "testKey", 
    "type": "APPLICATION", 
    "runnableContext": "testContext" 
} 
} 

Я не может прочитать часть «данные» из вышеприведенной JSON записанной в файл в объект JsonData благодаря вышеприведенной ошибке.

Пожалуйста посоветуйте

Благодарности

ответ

1

см https://sites.google.com/site/gson/gson-user-guide#TOC-Serializing-and-Deserializing-Generic-Types

При вызове toJson (объект), Gson звонки obj.getClass(), чтобы получить информацию о полях для сериализации. Аналогично, вы можете передать объект MyClass.class в методе fromJson (json, MyClass.class). Это отлично работает, если объект является не общим типом. Однако, если объект имеет общий тип, информация типа Generic теряется из-за Java Type Erasure. Ниже приведен пример, иллюстрирующий пункт:

class Foo<T> { 
    T value; 
} 
Gson gson = new Gson(); 
Foo<Bar> foo = new Foo<Bar>(); 
gson.toJson(foo); // May not serialize foo.value correctly 

gson.fromJson(json, foo.getClass()); // Fails to deserialize foo.value as Bar 

Приведенный выше код не удается интерпретировать значение как тип Bar, потому что Gson вызывает list.getClass(), чтобы получить свою классовую информацию, но этот метод возвращает необработанный класс, Foo.class , Это означает, что Gson не знает, что это объект типа Foo, а не просто Foo.

Вы можете решить эту проблему, указав правильный параметризованный тип для вашего общего типа. Вы можете сделать это, используя класс TypeToken.

Type fooType = new TypeToken<Foo<Bar>>() {}.getType(); 
gson.toJson(foo, fooType); 

gson.fromJson(json, fooType); 

идиома используется, чтобы получить fooType фактически определяет анонимный локальный внутренний класс, содержащий метод GetType(), который возвращает полностью параметризованный тип.

Смежные вопросы