Как преобразовать произвольный JSON в полезную структуру в Java

Я пытаюсь использовать gson для преобразования этого возвращенного JSON в какой-то так что я могу извлечь полезные данные.

Пример:

http://search.twitter.com/search.json?q=test&rpp=1

Возврат:

{
    "completed_in":0.028,
    "max_id":196386333906837504,
    "max_id_str":"196386333906837504",
    "next_page":"?page=2&max_id=196386333906837504&q=test&rpp=1",
    "page":1,
    "query":"test",
    "refresh_url":"?since_id=196386333906837504&q=test",
       "results":[
          {
             "created_at":"Sat, 28 Apr 2012 23:52:05 +0000",
             "from_user":"della_ky",
             "from_user_id":525641596,
             "from_user_id_str":"525641596",
             "from_user_name":"kydella modeste",
             "geo":null,
             "id":196386333906837504,
             "id_str":"196386333906837504",
             "iso_language_code":"en",
             "metadata":{
                "result_type":"recent"
             },
             "profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/2159990525\/webcam-toy-photo3_20_2__normal.jpg",
             "profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/2159990525\/webcam-toy-photo3_20_2__normal.jpg",
             "source":"<a href="http:\/\/mobile.twitter.com" rel="nofollow">Mobile Web<\/a>",
             "text":"RT @Y__U__NOOO: #SongsIKnowOffByHeart ALL SONGS I LISTEN TO. BRAIN, Y U NO REMEMBER TEST ANSWERS LIKE THAT?!?",
             "to_user":null,
             "to_user_id":null,
             "to_user_id_str":null,
             "to_user_name":null
          }
       ],
       "results_per_page":1,
       "since_id":0,
       "since_id_str":"0"
    }

В конечном счете, я хотел бы иметь возможность выводить список твитов с помощью имя отправителя и дата/время твита.

Я прочитал документацию gson, но это перевернулось если честно - там много новых концепций.

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

Кто-нибудь может дать мне несколько указателей? Будучи новичком в этом - чем больше подробно и в словах наименьших слогов, тем лучше!

Обновление. Благодаря ответам, которые у меня уже были на этом, у меня было желание собрать класс вместе, чтобы захватить твиттер JSON. Однако, поскольку JSON имеет встроенный ArrayList объектов, я немного борюсь... До сих пор у меня

public class tweetData {
    private double completed_in;
    private long max_id;
    private long max_id_str;
    private String next_page;
    private int page;
    private String query;
    private String refresh_url;
    private List<tweetDetails> tweets = new ArrayList<tweetDetails>();
}

и

public class tweetDetails {
    private String created_at;
    private String from_user;
    private long from_user_id;
    private long from_user_id_str;
    private String from_user_name;
    private String geo;
    private long id;
    private long id_str;
    private String iso_language_code;
//  "metadata":
//  {
//  "result_type":"recent"
//  },
    private String profile_image_url;
    private String profile_image_url_https;
    private String source;
    private String text;
    private String to_user;
    private String to_user_id;
    private String to_user_id_str;
    private String to_user_name;
}

Что я создаю с помощью

URI uri = new URI("http", "search.twitter.com", "/search.json", "q="+ searchTerms + "&rrp=" + RRP, null);
URL twitterSearch = uri.toURL();
URLConnection yc = twitterSearch.openConnection();
JsonReader reader = new JsonReader(new InputStreamReader(yc.getInputStream()));
Gson gson = new Gson();
tweetData data = gson.fromJson(reader, tweetData.class);
System.out.println(data);

Основное имя: значения заполняются правильно, но ArrayList не является.

tweetData : 0.17196614959919140865196614959919140865?page=2&max_id=196614959919140865&q=test1test?since_id=196614959919140865&q=testSIZE 0[]

Итак, я все еще немного борюсь - больше советов очень ценится!

Тиа, Том

Ответ 1

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

Да. GSON - это библиотека, которая может быть использована для преобразования объектов Java в их представление JSON. Его также можно использовать для преобразования строки JSON в эквивалентный объект Java. Это действительно эффективно, потому что вы можете автоматически создавать объекты Java из представления JSON. Предполагая, что ваш JSON не меняет свою структуру, вам нужно только определить соответствующее представление объекта Java один раз.

В идеале я ищу что-то, что будет обрабатывать JSON в любой форме и дать мне структуру, которую я могу использовать автоматически...

Однако, если вам не нужна автоматическая сериализация/десериализация, попробуйте взглянуть на более простую библиотеку, такую ​​как java.net/projects/jsonp.

Вы можете извлечь материал из него, просто запросив ключи:

final JSONObject json = new JSONObject(theJsonString);
final String id = json.getString("max_id");
final JSONArray results = json.getJSONArray("results");
final String user = results.getJSONObject(2).getString("from_user");

Ответ 2

Gson фактически выполняет всю сериализацию для вас. Так что да, вам придется писать классы самостоятельно. Для вас эти швы негибкие и трудоемкие, но только потому, что эта библиотека не предназначена для того, что вы просите (она не анализирует "произвольный" JSON).

Я бы предложил по крайней мере рассмотреть возможность написания классов и использования gson. Причина, по которой я говорю, заключается в том, что в любом случае ваша прикладная логика должна будет ожидать особого формата, и запись этого формата в классе Java сделает вещи более аккуратными. Вот хороший guide, который поможет вам начать работу таким образом.

Если вы хотите просто декодировать JSON без сериализации его в Java-классе (IMHO - единственный способ использования "произвольного" JSON), вы захотите использовать другую библиотеку. Попробуйте этот. Он позволяет вам декодировать JSON и использовать его, получая из него значения (как описано в этом вопросе: Преобразовать строку JSON в объект Java ME?).

Ответ 3

Есть некоторые инструменты, которые делают gson для сопоставления схемы. Вы даете несколько примеров ответов JSON, и классы java для их доступа создаются для вас.

http://www.jsonschema2pojo.org/

Ответ 4

Gson - это зверь! Или, по крайней мере, это стало на протяжении многих лет, прошедших после того, как вопрос был задан.

Вы можете передать его Object.class как второй параметр в метод fromJson(), и он проанализирует ваш Json в разумной структуре LinkedTreeMap и ArrayList.

Object result = (new Gson()).fromJson(jsonString, Object.class)

Более того, вы можете сделать частичный синтаксический анализ и оставить свободные концы на любом уровне своей структуры объекта, определив определенное поле как Object!

Gson затем проанализирует Json в вашей структуре, и ваше поле типа Object будет содержать вышеупомянутую структуру LinkedTreeMap и ArrayList..

Например, вы можете определить класс

Person {
    String name;
    Object details;
}

(Предположим, вы больше всего заботитесь о имени человека, но можете, возможно, и его детали, например, для их регистрации.)

Затем вы можете передать следующий Json в метод fromJson (input, Person.class) в качестве первого параметра

{ 
    "name": "Carlsson", 
    "details": {
        "address": "Stockholm",
        "phones": [
            "work": "233-322-233-322",
            "home": "none"
        ]
    }
}

В результате будет поле имя, заполненное строкой "Carlsson" , а поле details будет содержать LinkedTreeMap. > с ключами " и " телефонами и т.д.