JSON и Generics в Java - Введите предупреждение о безопасности

У меня есть некоторые данные, хранящиеся в элементах Java, и мне нужно вернуть их в заданном формате - JSONObject. Хотя моя реализация работает нормально, я все еще получаю предупреждение от eclipse (Версия: Juno Service Release 2):

"Тип безопасности: метод put (Object, Object) относится к необработанному типу HashMap. Ссылки на общий тип HashMap следует параметризовать"

Это мой код:

public interface Element {...}

public abstract class AbstractElement implements Element {...}

public final class Way extends AbstractElement {...}

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

public class WayToJsonConverter{
    ...
    public JSONObject wayToJson(){
        JSONObject obj = new JSONObject();
        obj.put("id",way.getId());
        ...
        return obj;
    }
    ...
}

Проблемная строка: obj.put("id",way.getId());

Есть ли способ решить эту проблему, а затем добавить @SuppressWarnings("unchecked")?

Ответ 1

Каков ваш JSONObject, он наследуется от HashMap? Если это так, предупреждение, вероятно, означает, что ваш должен объявить экземпляр JSONObject следующим образом:

JSONObject<String,Object> obj=new JSONObject<String,Object>();

Обновлено: Посмотрите на определение JSONObject:

public class JSONObject extends HashMap

он расширяет HashMap, но не поддерживает тип параметра, если его определение

public class JSONObject<K,V> extends HashMap<K,V>

то мы могли бы написать

JSONObject<String,Object> obj=new JSONObject<String,Object>();

и метод put больше не будет генерировать предупреждение

Ответ 2

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

Таким образом, у вас будет свой собственный класс JSONObject, который будет содержать org.json.simple.JSONObject, расширяет HashMap<String, Object> и реализует Map<String, Object> и будет содержать методы пересылки для всех методов org.json.simple.JSONObject.

Вам все равно придется помещать @SuppressWarnings("unchecked") в этот класс, но он будет ограничен этим классом, и весь остальной код может быть свободен от общих предупреждений или подавления их.

Ответ 3

FYI org.codehaus.jettison.json.JSONObject не будет вызывать это предупреждение. При использовании JSONObject от Codehaus у вас также есть возможность поймать ошибки анализа с помощью org.codehaus.jettison.json.JSONException. Подробнее см. https://github.com/codehaus/jettison.

Ответ 4

Вы можете создать объект карты, а затем выполнить явное преобразование в JSONObject

Map<String, String> obj =  new HashMap<String, String>();
obj.put("id",way.getId());
JSONObject jsonObj =  (JSONObject) obj;

Но обратите внимание, что это ограничит вас только включением "Строки" в вашем JSON. и вы увидите ошибки компиляции, если вы поместите другую структуру данных. Скажем массив.

Ответ 5

Другой вариант - инициализировать JSONObject с помощью (параметризованного) Map<String, Object>. Таким образом, значение может быть любого допустимого типа JSON, и вы избегаете предупреждения unchecked. Например:.

public class WayToJsonConverter{
    ...
    public JSONObject wayToJson(){
        Map<String, Object> forJsonObj = new HashMap<>();
        forJsonObj.put("id",way.getId());  // No warning, hurray!
        forJsonObj.put("integer", 14);
        forJsonObj.put("floating", 1.4);
        JSONObject obj = new JSONObject(forJsonObj);
        ...
        return obj;
    }
    ...
}