Nano Hash - криптовалюты, майнинг, программирование

Преобразование JSON во вложенный объект (общий объект) с помощью GSON

Я хочу создать парсер для разбора JSON с помощью Gson.

Первый IParser.java

public interface IParser<T> {
    public T parse(String json);
}

Второй Parser.java

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

public class Parser<T> implements IParser<T> {

    @Override
    public T parse(String json) {
        GsonBuilder builder = new GsonBuilder();
        Gson gson = builder.enableComplexMapKeySerialization().create();
        MyJson<T> jsonParsed = gson.fromJson(json, new TypeToken<MyJson<T>>() {
        }.getType());

        System.out.println(jsonParsed.toString());
        return null;
    }

}

Третий MyJson.java

public class MyJson<T> {
    private int status;
    private T data;

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

И User.java

import java.io.Serializable;

public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private long usrId;
    private String usrNm;
    private String usrPwd;
    private String usrEml;

    public User() {

    }

    public long getUsrId() {
        return usrId;
    }

    public void setUsrId(long usrId) {
        this.usrId = usrId;
    }

    public String getUsrNm() {
        return usrNm;
    }

    public void setUsrNm(String usrNm) {
        this.usrNm = usrNm;
    }

    public String getUsrPwd() {
        return usrPwd;
    }

    public void setUsrPwd(String usrPwd) {
        this.usrPwd = usrPwd;
    }

    public String getUsrEml() {
        return usrEml;
    }

    public void setUsrEml(String usrEml) {
        this.usrEml = usrEml;
    }

    @Override
    public String toString() {
        return "User [usrId=" + usrId + ", usrNm=" + usrNm + ", usrPwd="
                + usrPwd + ", usrEml=" + usrEml + "]";
    }
}

Моя строка JSON:

{
    status: 200,
    data: {
        usrId: 2,
        usrNm: "John",
        usrPwd: "123",
        usrEml: "[email protected]"
    }
}

Я хочу разобрать выше jsonString до объекта MyJson<T>.

I do:

MyJson<T> jsonParsed = gson.fromJson(json, new TypeToken<MyJson<T>>() {
            }.getType());

=> Gson анализирует мои User в MyJson до LinkedTreeMap

Это означает: Object data = jsonParsed.getData(); => экземпляр данных LinkedTreeMap

Что я хочу: экземпляр данных User

Но, когда я пытаюсь:

MyJson<User> jsonParsed = gson.fromJson(json, new TypeToken<MyJson<User>>() {
            }.getType());

gson работает нормально.

Итак, я хочу знать, как заставить gson работать нормально с первым способом (используйте T вместо User), потому что я хочу проанализировать другой объект с помощью Parser.

Спасибо за вашу помощь.

24.02.2014

  • Ответ таков: вы не можете этого сделать из-за стирания типа. Прием TypeToken, который использует Гсон, работает только тогда, когда тип передается явно. Тип T полностью стирается во время выполнения. 24.02.2014
  • Дублирование: токен типа Gson с динамическим типом 24.02.2014
  • @BrianRoach: Это здорово! Огромное спасибо 25.02.2014
  • Ваше решение не может решить мою проблему. :( 25.02.2014
  • Это не решение; это объясняет, что, опять же, вы не можете делать то, что пытаетесь сделать. 25.02.2014
  • Спасибо, я решил эту проблему. :D 25.02.2014
  • @JackDuong Можете ли вы поделиться своим решением? Так как я сталкиваюсь с той же проблемой. Я получаю LinkedTreeMap вместо своего экземпляра объекта. 20.04.2015

Ответы:


1
@Override
public T parse(String json, Type type) {
    GsonBuilder builder = new GsonBuilder();
    Gson gson = builder.enableComplexMapKeySerialization().create();
    MyJson<T> jsonParsed = gson.fromJson(json, type);

    System.out.println(jsonParsed.toString());
    return null;
}

С использованием:

User user = myJson.parse(jsonString, new TypeToken<User>() {
        }.getType());
25.02.2014
  • Это то, что я сделал. Спасибо, сэр. :) 25.02.2014

  • 2

    Как отмечают другие, проблема заключается в том, что TypeToken должен быть создан со всеми конкретными типами (т.е. не параметризован ни с каким T). Таким образом, вам нужно, чтобы вызывающая сторона создавала экземпляр TypeToken для вас (здесь вы являетесь классом Parser).

    Принятый ответ Джона работает (если вы игнорируете тот факт, что он возвращает null и вместо этого печатает результат), но я думаю, что лучше обеспечить совместимость параметра Type с возвращаемым типом, например так:

    public T parse(String json, TypeToken<MyJson<T>> typeToken) {
        MyJson<T> deserializedMyJson = gson.fromJson(json, typeToken.getType());
        return deserializedMyJson.getData();
    }
    

    И это будет обеспечивать во время компиляции, что любой вызов parse() передается правильным TypeToken, так что что-то вроде

    A a = parser.parse(jsonString, new TypeToken<MyJson<B>>(){});  // incorrect
    

    произойдет сбой во время компиляции, в то время как что-то вроде этого (при условии, что метод parse() принимает Type в качестве параметра):

    A a = parser.parse(jsonString, new TypeToken<MyJson<B>>(){}.getType());  // incorrect too, but will compile
    

    завершится ошибкой только во время выполнения (при попытке преобразовать результат B выполнения parse() в переменную a типа A).

    15.05.2014
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

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

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..