A fully pluggable JSON streaming library abstraction allows you to take advantage of the nativeplatform’s built-in JSON library support (for example the JSON library that is built into AndroidHoneycomb). The streaming library enables you to write optimized code for efficient memory usagethat minimizes parsing and serialization time.
A big advantage of this JSON library is that the choice of low-level streaming library is fullypluggable. There are three built-in choices, all of which extendJsonFactory. Youcan easily plug in your own implementation.
JacksonFactory: Based on the popularJackson library, which isconsidered the fastest in terms of parsing/serialization speed. Our JSON library providesJsonFactory implementations based on Jackson 2.GsonFactory: Based on theGoogle GSON library, which is a lighter-weightoption (small size) that is also fairly fast, though not as fast as Jackson.AndroidJsonFactory (@Beta): Based on the JSON library built intoAndroid Honeycomb (SDK 3.0) and higher, and that is identical to the Google GSON library.User-defined JSON data models allow you to define Plain Old Java Objects (POJOs) and define how thelibrary parses and serializes them to and from JSON. The code snippets below are part of a morecomplete example,YouTube sample, which demonstrates theseconcepts.
The following JSON snippet shows the relevant fields of a typicalYouTube video search:
{"kind":"youtube#searchListResponse","pageInfo":{"totalResults":1000000,"resultsPerPage":5},"items":[{"kind":"youtube#searchResult","id":{"kind":"youtube#video","videoId":"e6Tudp5lqt8"},"snippet":{"publishedAt":"2020-06-25T23:18:43Z","channelId":"UCKwGZZMrhNYKzucCtTPY2Nw","title":"Video 1 Title","description":"Video 1 Description","thumbnails":{"default":{"url":"https://i.ytimg.com/vi/e6Tudp5lqt8/default.jpg","width":120,"height":90},"medium":{"url":"https://i.ytimg.com/vi/e6Tudp5lqt8/mqdefault.jpg","width":320,"height":180},"high":{"url":"https://i.ytimg.com/vi/e6Tudp5lqt8/hqdefault.jpg","width":480,"height":360}}}},{"kind":"youtube#searchResult","id":{"kind":"youtube#video","videoId":"o-NtLpiMpw0"},"snippet":{"publishedAt":"2020-06-25T17:28:52Z","channelId":"UClljAz6ZKy0XeViKsohdjqA","title":"Video Title 2","description":"Video 2 Description","thumbnails":{"default":{"url":"https://i.ytimg.com/vi/o-NtLpiMpw0/default.jpg","width":120,"height":90},"medium":{"url":"https://i.ytimg.com/vi/o-NtLpiMpw0/mqdefault.jpg","width":320,"height":180},"high":{"url":"https://i.ytimg.com/vi/o-NtLpiMpw0/hqdefault.jpg","width":480,"height":360}}}},{"kind":"youtube#searchResult","id":{"kind":"youtube#video","videoId":"TPAahzXZFZo"},"snippet":{"publishedAt":"2020-06-26T15:45:00Z","channelId":"UCR4Yfr8HAZJd9X24dwuAt1Q","title":"Video 3 Title","description":"Video 3 Description","thumbnails":{"default":{"url":"https://i.ytimg.com/vi/TPAahzXZFZo/default.jpg","width":120,"height":90},"medium":{"url":"https://i.ytimg.com/vi/TPAahzXZFZo/mqdefault.jpg","width":320,"height":180},"high":{"url":"https://i.ytimg.com/vi/TPAahzXZFZo/hqdefault.jpg","width":480,"height":360}}}},{"kind":"youtube#searchResult","id":{"kind":"youtube#video","videoId":"gBL-AelsdFk"},"snippet":{"publishedAt":"2020-06-24T15:24:06Z","channelId":"UCFHZHhZaH7Rc_FOMIzUziJA","title":"Video 4 Title","description":"Video 4 Description","thumbnails":{"default":{"url":"https://i.ytimg.com/vi/gBL-AelsdFk/default.jpg","width":120,"height":90},"medium":{"url":"https://i.ytimg.com/vi/gBL-AelsdFk/mqdefault.jpg","width":320,"height":180},"high":{"url":"https://i.ytimg.com/vi/gBL-AelsdFk/hqdefault.jpg","width":480,"height":360}}}},{"kind":"youtube#searchResult","id":{"kind":"youtube#video","videoId":"9ofe8axKjH0"},"snippet":{"publishedAt":"2020-06-26T11:59:32Z","channelId":"UCtNpbO2MtsVY4qW23WfnxGg","title":"Video 5 Title","description":"Video 5 Description","thumbnails":{"default":{"url":"https://i.ytimg.com/vi/9ofe8axKjH0/default.jpg","width":120,"height":90},"medium":{"url":"https://i.ytimg.com/vi/9ofe8axKjH0/mqdefault.jpg","width":320,"height":180},"high":{"url":"https://i.ytimg.com/vi/9ofe8axKjH0/hqdefault.jpg","width":480,"height":360}}}}]}Here’s one possible way to design the Java data classes to represent this:
publicstaticclassListResponse{@Key("items")privateList<SearchResult>searchResults;@KeyprivatePageInfopageInfo;publicList<SearchResult>getSearchResults(){returnsearchResults;}publicPageInfogetPageInfo(){returnpageInfo;}}publicstaticclassPageInfo{@KeyprivatelongtotalResults;@KeyprivatelongresultsPerPage;publiclonggetTotalResults(){returntotalResults;}publiclonggetResultsPerPage(){returnresultsPerPage;}}publicstaticclassSearchResult{@KeyprivateStringkind;@Key("id")privateVideoIdvideoId;@KeyprivateSnippetsnippet;publicStringgetKind(){returnkind;}publicVideoIdgetId(){returnvideoId;}publicSnippetgetSnippet(){returnsnippet;}}publicstaticclassVideoId{@KeyprivateStringkind;@KeyprivateStringvideoId;publicStringgetKind(){returnkind;}publicStringgetVideoId(){returnvideoId;}}publicstaticclassSnippet{@KeyprivateStringpublishedAt;@KeyprivateStringchannelId;@KeyprivateStringtitle;@KeyprivateStringdescription;publicStringgetPublishedAt(){returnpublishedAt;}publicStringgetChannelId(){returnchannelId;}publicStringgetTitle(){returntitle;}publicStringgetDescription(){returndescription;}publicMap<String,Thumbnail>getThumbnails(){returnthumbnails;}}publicstaticclassThumbnail{@KeyprivateStringurl;@Keyprivatelongwidth;@Keyprivatelongheight;publicStringgetUrl(){returnurl;}publiclonggetWidth(){returnwidth;}publiclonggetHeight(){returnheight;}}A fully supportedHTTP JSON parser makes it easy to parse HTTP responses to objectsof these user defined classes:
publicstaticListResponseparseJson(HttpResponsehttpResponse)throwsIOException{ListResponselistResponse=httpResponse.parseAs(ListResponse.class);if(listResponse.getSearchResults().isEmpty()){System.out.println("No results found.");}else{for(SearchResultsearchResult:listResponse.getSearchResults()){System.out.println();System.out.println("-----------------------------------------------");System.out.println("Kind: "+searchResult.getKind());System.out.println("Video ID: "+searchResult.getId().getVideoId());System.out.println("Title: "+searchResult.getSnippet().getTitle());System.out.println("Description: "+searchResult.getSnippet().getDescription());}}returnlistResponse;}Use the@Key annotation to indicate fields that need to be parsed from orserialized to JSON. By default, the@Key annotation uses the Java field name as the JSON key. Tooverride this, specify the value of the@Key annotation.
Fields that don’t have the@Key annotation are considered internal data and are not parsed from orserialized to JSON.
Visibility of the fields does not matter, nor does the existence of the getter or setter methods. Sofor example, the following alternative representation forVideoId would work in the examplegiven above:
publicstaticclassVideoId{@KeypublicStringkind;@KeypublicStringvideoId;}Normally only the fields you declare are parsed when a JSON response is parsed. The actual Google+activity feed response contains a lot of content that we are not using in our example. The JSONparser skips that other content when parsing the response from Google+.
To retain the other content, declare your class to extendGenericJson. Notice thatGenericJson implementsMap, so we can use theget andput methods to set JSONcontent. SeeYoutube sample for an example of how it wasused in theSnippet class above.
The JSON library supports any implementation ofMap, which works similarly toGenericJson. Thedownside, of course, is that you lose the static type information for the fields.
One advantage of this JSON library is its ability to support JSON nulls and distinguish them fromundeclared JSON keys. Although JSON nulls are relatively rare, when they do occur they often causeconfusion.
Google+ doesn’t use JSON null values, so the following example uses fictitious JSON data toillustrate what can happen:
{"items":[{"id":"1","value":"some value"},{"id":"2","value":null}{"id":"3"}]}We might represent each item as follows:
publicclassItem{@KeypublicStringid;@KeypublicStringvalue;}For items 2 and 3, what should be in the value field? The problem is that there is no obvious way inJava to distinguish between a JSON key that is undeclared and a JSON key whose value is JSON null.This JSON library solves the problem by using Java null for the common case of an undeclared JSONkey, and a special “magic” instance of String (Data.NULL_STRING) to identify it asa JSON null rather than a normal value.
The following example shows how you might take advantage of this functionality:
privatestaticvoidshow(List<Item>items){for(Itemitem:items){System.out.println("ID: "+item.id);if(item.value==null){System.out.println("No Value");}elseif(Data.isNull(item.value)){System.out.print("Null Value");}else{System.out.println("Value: '"+item.value+"'");}}}