Как проще всего проанализировать json с помощью gson, если элемент для разбора является элементом строки json? - PullRequest
12 голосов
/ 22 сентября 2010

Я использую gson для разбора json на Java-бины.Для API, который я использую, большое количество результатов json включает результат в качестве первого свойства объекта json.«Способ gson», по-видимому, заключается в создании эквивалентного Java-объекта-оболочки, который имеет одно свойство для целевого типа вывода, но это приводит к ненужным одноразовым классам.Есть ли лучший способ сделать это?

Например, для разбора: {"profile":{"username":"nickstreet","first_name":"Nick","last_name":"Street"}}

Мне нужно сделать:

public class ParseProfile extends TestCase {
    public void testParseProfile() {
        Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
        String profileJson = "{\"profile\":{\"username\":\"nickstreet\",\"first_name\":\"Nick\",\"last_name\":\"Street\"}}";
        ProfileContainer profileContainer = gson.fromJson(profileJson, ProfileContainer.class);
        Profile profile = profileContainer.getProfile();
        assertEquals("nickstreet", profile.username);
        assertEquals("Nick", profile.firstName);
        assertEquals("Street", profile.lastName);
    }
}

public class ProfileContainer {
    protected Profile profile;

    public Profile getProfile() {
        return profile;
    }

    public void setProfile(Profile profile) {
        this.profile = profile;
    }
}

public class Profile {
    protected String username;
    protected String firstName;
    protected String lastName;

    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

Конечно, альтернативный подход киспользование контейнера означало бы ручное удаление внешней части строки (т.е. удаление "профиля": {и закрытие}) с использованием стандартных методов анализа строк, но это похоже на неправильный подход.

Я бы хотелчтобы иметь возможность делать что-то вроде:

Profile p = gson.fromJsonProperty(json, Profile.class, "profile");

Эта проблема предполагает, что должна быть возможность разбить строку json на объект json, чтобы извлечь элемент jsonElement из этого объекта,и передайте его в json.fromJson ().Однако метод toJsonElement () работает только с Java-объектом, а не с JSON-строкой.

У кого-нибудь есть лучший подход?

1 Ответ

8 голосов
/ 16 декабря 2010

Я столкнулся с той же проблемой.В основном, что вы делаете, чтобы избежать всякой бессмыслицы класса контейнера, просто используете функции JSONObject для извлечения внутреннего объекта, который вы пытаетесь десериализовать.Простите за небрежный код, но он выглядит примерно так:

GsonBuilder gsonb = new GsonBuilder()
Gson gson = gsonb.create();

JSONObject j;
JSONObject jo;

Profile p = null;

try {

    j = new JSONObject(convertStreamToString(responseStream));
    jo = j.getJSONObject("profile"); // now jo contains only data within "profile"
    p = gson.fromJson(jo.toString(), Profile.class);
    // now p is your deserialized profile object
}catch(Exception e) {
    e.printStackTrace();
}
...