Gson使用泛型类型

时间:2015-06-27 21:15:14

标签: java unit-testing gson

我将以下json写入我希望通过Gson阅读的文件中:

{
  "identifier": "CONFIG",
  "data": [
    {
      "identifier": "HOTKEY",
      "data": {
        "hotKey": "testKey1",
        "type": "APPLICATION",
        "runnableContext": "testContext1"
      }
    },
    {
      "identifier": "HOTKEY",
      "data": {
        "hotKey": "testKey2",
        "type": "APPLICATION",
        "runnableContext": "testContext2"
      }
    }
  ]
}

在上面的Json中,您可以看到标识符&数据结构是递归重复的。因此,表示此重复模式的基本类是通用的,如下所示:

{
  "identifier": "CONFIG",
  "data": {

  }
}

此模式由JsonData类表示如下:

import java.util.Set;

....
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","HOTKEY","RECOMMENDATIONS");

    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中,您可以看到每个热键内的数据。在通过gson:

读取json之后,此数据将保存在ConfigurationProperty类中
public class ConfigurationProperty implements Comparable<ConfigurationProperty>, Serializable{
....    
private final String hotKey;
private final String type;
private final String runnableContext;
....

现在的问题。我正在尝试读取文件并解析Json以使用GSON将其存储到相应的对象中而没有运气。

我有一些工作代码来读取写入文件的单个JsonData对象:

    {
      "identifier": "HOTKEY",
      "data": {
        "hotKey": "testKey1",
        "type": "APPLICATION",
        "runnableContext": "testContext1"
      }
    }

成功阅读:

private static JsonData<ConfigurationProperty> readconfigFile() {
    Reader reader = null;
    JsonData<ConfigurationProperty> data = null;
    Gson gson  = null;
    Type confType;
    try {
        reader = new FileReader("./config.json");
        gson = new GsonBuilder().create();
        confType = new TypeToken<JsonData<ConfigurationProperty>>() {}.getType();

        data = gson.fromJson(reader,confType);
    } 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;
}

但是如果你看第一个json,这现在是JsonData的递归结构。同样在解析时,我需要告诉Gson第一个数据对象是JSONData对象的ARRAY。我还需要告诉gson该数组中的每个JSONData对象都是ConfigurationProperty类型。

我不知道该怎么做。

2 个答案:

答案 0 :(得分:2)

我明白了。我就这样做了

    private static JsonData<List<ConfigurationProperty>> readconfigFileList() {
    Reader reader = null;
    JsonData<List<ConfigurationProperty>> dataArray = null;
    Gson gson  = null;
    Type confType;
    Type confTypeArray;
    try {
        reader = new FileReader("./config.json");
        gson = new GsonBuilder().create();
        confType = new TypeToken<JsonData<List<ConfigurationProperty>>>() {}.getType();

        dataArray = gson.fromJson(reader,confType);
        System.out.println(dataArray.toString());

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

答案 1 :(得分:1)

使用Gson库找到以下用于通用Json对象解析或未知Json对象解析的代码。

public class JsonParsing {

    static JsonParser parser = new JsonParser();

    public static HashMap<String, Object> createHashMapFromJsonString(String json) {

        JsonObject object = (JsonObject) parser.parse(json);
        Set<Map.Entry<String, JsonElement>> set = object.entrySet();
        Iterator<Map.Entry<String, JsonElement>> iterator = set.iterator();
        HashMap<String, Object> map = new HashMap<String, Object>();

        while (iterator.hasNext()) {

            Map.Entry<String, JsonElement> entry = iterator.next();
            String key = entry.getKey();
            JsonElement value = entry.getValue();

            if (null != value) {
                if (!value.isJsonPrimitive()) {
                    if (value.isJsonObject()) {

                        map.put(key, createHashMapFromJsonString(value.toString()));
                    } else if (value.isJsonArray() && value.toString().contains(":")) {

                        List<HashMap<String, Object>> list = new ArrayList<>();
                        JsonArray array = value.getAsJsonArray();
                        if (null != array) {
                            for (JsonElement element : array) {
                                list.add(createHashMapFromJsonString(element.toString()));
                            }
                            map.put(key, list);
                        }
                    } else if (value.isJsonArray() && !value.toString().contains(":")) {
                        map.put(key, value.getAsJsonArray());
                    }
                } else {
                    map.put(key, value.getAsString());
                }
            }
        }
        return map;
    }
}

〜钱德拉