List of usage examples for com.google.gson.stream JsonReader JsonReader
public JsonReader(Reader in)
From source file:com.flowzr.budget.holo.export.flowzr.FlowzrSyncEngine.java
License:Open Source License
public static <T> int getJSONFromUrl(String url, String tableName, Class<T> clazz, long last_sync_ts) throws IOException, JSONException, Exception { if (url == null) { return 0; }/*from w w w.java 2 s . co m*/ HttpGet httpGet = new HttpGet(url); httpGet.addHeader("Cookie", "dev_appserver_login=test@example.com:False:185804764220139124118"); HttpResponse httpResponse = http_client.execute(httpGet); HttpEntity httpEntity = httpResponse.getEntity(); // All the work is done for you here :) String jsonContent = EntityUtils.toString(httpEntity); // Create a Reader from String Reader stringReader = new StringReader(jsonContent); //is = httpEntity.getContent(); reader = new JsonReader(stringReader); reader.setLenient(true); reader.beginObject(); int i = readMessage(reader, tableName, clazz, last_sync_ts); httpEntity.consumeContent(); return i; }
From source file:com.flowzr.budget.holo.export.flowzr.FlowzrSyncEngine.java
License:Open Source License
public static void pullDelete(long last_sync_ts) throws Exception { String url = FLOWZR_API_URL + nsString + "/delete/?last_sync_ts=" + last_sync_ts; HttpGet httpGet = new HttpGet(url); HttpResponse httpResponse = http_client.execute(httpGet); HttpEntity httpEntity = httpResponse.getEntity(); is = httpEntity.getContent();/*ww w. j ava 2 s .c o m*/ reader = new JsonReader(new InputStreamReader(is, "UTF-8")); reader.beginObject(); readDelete(reader); httpEntity.consumeContent(); }
From source file:com.fsryan.forsuredb.api.migration.MigrationRetrieverFactory.java
License:Apache License
public MigrationRetriever fromStream(final InputStream inputStream) { return new MigrationRetriever() { private MigrationSet migrationSet; @Override//from w w w .j av a 2 s. c om public List<MigrationSet> getMigrationSets() { if (migrationSet == null) { migrationSet = createMigrationSet(); } return Lists.newArrayList(migrationSet); } @Override public int latestDbVersion() { if (migrationSet == null) { migrationSet = createMigrationSet(); } return migrationSet.getDbVersion(); } private MigrationSet createMigrationSet() { JsonReader reader = new JsonReader(new InputStreamReader(inputStream)); try { return gson.fromJson(reader, new TypeToken<MigrationSet>() { }.getType()); } catch (Exception e) { e.printStackTrace(); } finally { try { reader.close(); } catch (IOException e) { } } // return a dummy MigrationSet if the error was found return MigrationSet.builder().dbVersion(-1).build(); } }; }
From source file:com.funambol.android.activities.AndroidHomeScreen.java
License:Open Source License
/** * json//from www. ja v a 2s. com * @param in * @throws IOException */ public void processJsonStream(InputStream in) throws IOException { JsonReader reader = new JsonReader(new InputStreamReader(in, "UTF-8")); reader.beginObject(); boolean result = false; int contactsCount = 0; // int smsCount = 0; // long smsLastBakTime = 0; // while (reader.hasNext()) { String name = reader.nextName(); if ("result".equals(name)) { result = "ok".equals(reader.nextString()); } else if ("contacts_count".equals(name)) { contactsCount = Integer.valueOf(reader.nextString()); } else if ("sms_count".equals(name)) { smsCount = Integer.valueOf(reader.nextString()); } else if ("sms_last_baktime".equals(name)) { try { smsLastBakTime = Long.valueOf(reader.nextString()); } catch (NumberFormatException e) { e.printStackTrace(); } } else { reader.skipValue(); } } reader.endObject(); if (result) { //prefStore prefStore.setSmsCountInServer(this, smsCount); prefStore.setContactsCountInServer(this, contactsCount); // overviewInfoHandler.sendEmptyMessage(MSG_REFRESH_OVERVIEW_INFO); //0 if (0 == contactsCount) { contactsImportHandler.sendEmptyMessage(0); Log.debug("shawnqiu", "homeScreen : processJsonStream : showContactsImporter"); } } }
From source file:com.gelakinetic.mtgfam.helpers.JsonParser.java
License:Open Source License
public void readCardJsonStream(InputStream in, CardProgressReporter progReport, String setName, CardDbAdapter mDbHelper, Context context) throws IOException { String dialogText = String.format(context.getString(R.string.update_parse_cards), setName); JsonReader reader = new JsonReader(new InputStreamReader(in, "ISO-8859-1")); String s, s1, s2, ptstr;/* w w w . j a v a2s . c o m*/ int numTotalElements = 0; int elementsParsed = 0; reader.beginObject(); s = reader.nextName(); ArrayList<MtgSet> setsAdded = new ArrayList<MtgSet>(); progReport.reportJsonCardProgress("determinate", ""); reader.beginObject(); while (reader.hasNext()) { s = reader.nextName(); if (s.equalsIgnoreCase("v")) { // bdd_date reader.skipValue(); } if (s.equalsIgnoreCase("u")) { // bdd_version reader.skipValue(); } if (s.equalsIgnoreCase("s")) { // sets reader.beginObject(); while (reader.hasNext()) { s1 = reader.nextName(); if (s1.equalsIgnoreCase("b")) { // set MtgSet set; JsonToken jt = reader.peek(); if (jt.equals(JsonToken.BEGIN_OBJECT)) { set = new MtgSet(); reader.beginObject(); while (reader.hasNext()) { s2 = reader.nextName(); if (s2.equalsIgnoreCase("a")) { // name set.name = reader.nextString(); } if (s2.equalsIgnoreCase("r")) { // code_magiccards set.code_magiccards = reader.nextString(); } if (s2.equalsIgnoreCase("q")) { // code set.code = reader.nextString(); } if (s2.equalsIgnoreCase("y")) { // date set.date = reader.nextLong(); } } setsAdded.add(set); reader.endObject(); } else if (jt.equals(JsonToken.BEGIN_ARRAY)) { reader.beginArray(); while (reader.hasNext()) { set = new MtgSet(); reader.beginObject(); while (reader.hasNext()) { s2 = reader.nextName(); if (s2.equalsIgnoreCase("a")) { // name set.name = reader.nextString(); } if (s2.equalsIgnoreCase("r")) { // code_magiccards set.code_magiccards = reader.nextString(); } if (s2.equalsIgnoreCase("q")) { // code set.code = reader.nextString(); } if (s2.equalsIgnoreCase("y")) { // date set.date = reader.nextLong(); } } setsAdded.add(set); reader.endObject(); } reader.endArray(); } } } reader.endObject(); } if (s.equalsIgnoreCase("p")) { // cards reader.beginObject(); while (reader.hasNext()) { s1 = reader.nextName(); if (s1.equalsIgnoreCase("o")) { // card MtgCard c; reader.beginArray(); while (reader.hasNext()) { reader.beginObject(); c = new MtgCard(); while (reader.hasNext()) { s2 = reader.nextName(); if (s2.equalsIgnoreCase("a")) { // name c.name = reader.nextString(); } else if (s2.equalsIgnoreCase("b")) { // set c.set = reader.nextString(); } else if (s2.equalsIgnoreCase("c")) { // type c.type = reader.nextString(); } else if (s2.equalsIgnoreCase("d")) { // rarity c.rarity = reader.nextString().charAt(0); } else if (s2.equalsIgnoreCase("e")) { // manacost c.manacost = reader.nextString(); } else if (s2.equalsIgnoreCase("f")) { // converted_manacost try { c.cmc = reader.nextInt(); } catch (Exception e) { reader.skipValue(); } } else if (s2.equalsIgnoreCase("g")) { // power try { ptstr = reader.nextString(); try { c.power = Integer.parseInt(ptstr); } catch (NumberFormatException e) { if (ptstr.equals("*")) { c.power = CardDbAdapter.STAR; } else if (ptstr.equals("1+*")) { c.power = CardDbAdapter.ONEPLUSSTAR; } else if (ptstr.equals("2+*")) { c.power = CardDbAdapter.TWOPLUSSTAR; } else if (ptstr.equals("7-*")) { c.power = CardDbAdapter.SEVENMINUSSTAR; } else if (ptstr.equals("*{^2}")) { c.power = CardDbAdapter.STARSQUARED; } else if (ptstr.equals("{1/2}")) { c.power = 0.5f; } else if (ptstr.equals("1{1/2}")) { c.power = 1.5f; } else if (ptstr.equals("2{1/2}")) { c.power = 2.5f; } else if (ptstr.equals("3{1/2}")) { c.power = 3.5f; } } } catch (Exception e) { reader.skipValue(); } } else if (s2.equalsIgnoreCase("h")) { // toughness try { ptstr = reader.nextString(); try { c.toughness = Integer.parseInt(ptstr); } catch (NumberFormatException e) { if (ptstr.equals("*")) { c.toughness = CardDbAdapter.STAR; } else if (ptstr.equals("1+*")) { c.toughness = CardDbAdapter.ONEPLUSSTAR; } else if (ptstr.equals("2+*")) { c.toughness = CardDbAdapter.TWOPLUSSTAR; } else if (ptstr.equals("7-*")) { c.toughness = CardDbAdapter.SEVENMINUSSTAR; } else if (ptstr.equals("*{^2}")) { c.toughness = CardDbAdapter.STARSQUARED; } else if (ptstr.equals("{1/2}")) { c.toughness = 0.5f; } else if (ptstr.equals("1{1/2}")) { c.toughness = 1.5f; } else if (ptstr.equals("2{1/2}")) { c.toughness = 2.5f; } else if (ptstr.equals("3{1/2}")) { c.toughness = 3.5f; } } } catch (Exception e) { reader.skipValue(); } } else if (s2.equalsIgnoreCase("i")) { // loyalty try { c.loyalty = reader.nextInt(); } catch (Exception e) { reader.skipValue(); } } else if (s2.equalsIgnoreCase("j")) { // ability c.ability = reader.nextString(); } else if (s2.equalsIgnoreCase("k")) { // flavor c.flavor = reader.nextString(); } else if (s2.equalsIgnoreCase("l")) { // artist c.artist = reader.nextString(); } else if (s2.equalsIgnoreCase("m")) { // number try { c.number = reader.nextString(); } catch (Exception e) { reader.skipValue(); } } else if (s2.equalsIgnoreCase("n")) { // color c.color = reader.nextString(); } else if (s2.equalsIgnoreCase("x")) { // multiverse id c.multiverse_id = reader.nextInt(); } } mDbHelper.createCard(c); elementsParsed++; progReport.reportJsonCardProgress(new String[] { dialogText, dialogText, "" + (int) Math.round(100 * elementsParsed / (double) numTotalElements) }); reader.endObject(); } reader.endArray(); } } reader.endObject(); } if (s.equalsIgnoreCase("w")) { // num_cards numTotalElements = reader.nextInt(); } } reader.endObject(); reader.close(); // Add the set information to the database AFTER adding the cards. // This way if the update fails while parsing cards, the database won't think it has the set already, when it doesnt. for (MtgSet set : setsAdded) { mDbHelper.createSet(set); } return; }
From source file:com.gelakinetic.mtgfam.helpers.JsonParser.java
License:Open Source License
public ArrayList<String[]> readUpdateJsonStream(PreferencesAdapter prefAdapter) throws MalformedURLException, IOException { ArrayList<String[]> patchInfo = new ArrayList<String[]>(); URL update;//from ww w . ja v a 2 s. c o m String label; String label2; update = new URL("https://sites.google.com/site/mtgfamiliar/manifests/patches.json"); InputStreamReader isr = new InputStreamReader(update.openStream(), "ISO-8859-1"); JsonReader reader = new JsonReader(isr); reader.beginObject(); while (reader.hasNext()) { label = reader.nextName(); if (label.equals("Date")) { String lastUpdate = prefAdapter.getLastUpdate(); currentPatchDate = reader.nextString(); if (lastUpdate.equals(currentPatchDate)) { reader.close(); return null; } } else if (label.equals("Patches")) { reader.beginArray(); while (reader.hasNext()) { reader.beginObject(); String[] setdata = new String[3]; while (reader.hasNext()) { label2 = reader.nextName(); if (label2.equals("Name")) { setdata[0] = reader.nextString(); } else if (label2.equals("URL")) { setdata[1] = reader.nextString(); } else if (label2.equals("Code")) { setdata[2] = reader.nextString(); } } patchInfo.add(setdata); reader.endObject(); } reader.endArray(); } } reader.endObject(); reader.close(); return patchInfo; }
From source file:com.gelakinetic.mtgfam.helpers.JsonParser.java
License:Open Source License
public void readLegalityJsonStream(CardDbAdapter cda, PreferencesAdapter prefAdapter, boolean reparseDatabase) throws IOException, FamiliarDbException { CardDbAdapter mDbHelper;/* w w w. j av a 2s.com*/ String legalSet; String bannedCard; String restrictedCard; String formatName; String jsonArrayName; String jsonTopLevelName; URL legal = new URL("https://sites.google.com/site/mtgfamiliar/manifests/legality.json"); InputStream in = new BufferedInputStream(legal.openStream()); JsonReader reader = new JsonReader(new InputStreamReader(in, "ISO-8859-1")); mDbHelper = cda; reader.beginObject(); while (reader.hasNext()) { jsonTopLevelName = reader.nextName(); if (jsonTopLevelName.equalsIgnoreCase("Date")) { currentRulesDate = reader.nextString(); // compare date, maybe return, update sharedprefs String spDate = prefAdapter.getLegalityDate(); if (spDate != null && spDate.equals(currentRulesDate)) { if (!reparseDatabase) { // if we're reparsing, screw the date reader.close(); return; // dates match, nothing new here. } } mDbHelper.dropLegalTables(); mDbHelper.createLegalTables(); } else if (jsonTopLevelName.equalsIgnoreCase("Formats")) { reader.beginObject(); while (reader.hasNext()) { formatName = reader.nextName(); mDbHelper.createFormat(formatName); reader.beginObject(); while (reader.hasNext()) { jsonArrayName = reader.nextName(); if (jsonArrayName.equalsIgnoreCase("Sets")) { reader.beginArray(); while (reader.hasNext()) { legalSet = reader.nextString(); mDbHelper.addLegalSet(legalSet, formatName); } reader.endArray(); } else if (jsonArrayName.equalsIgnoreCase("Banlist")) { reader.beginArray(); while (reader.hasNext()) { bannedCard = reader.nextString(); mDbHelper.addLegalCard(bannedCard, formatName, CardDbAdapter.BANNED); } reader.endArray(); } else if (jsonArrayName.equalsIgnoreCase("Restrictedlist")) { reader.beginArray(); while (reader.hasNext()) { restrictedCard = reader.nextString(); mDbHelper.addLegalCard(restrictedCard, formatName, CardDbAdapter.RESTRICTED); } reader.endArray(); } } reader.endObject(); } reader.endObject(); } } reader.endObject(); reader.close(); return; }
From source file:com.gelakinetic.mtgfam.helpers.JsonParser.java
License:Open Source License
public void readTCGNameJsonStream(PreferencesAdapter prefAdapter, CardDbAdapter mDbHelper, boolean reparseDatabase) throws MalformedURLException, IOException, FamiliarDbException { URL update;/* www.j av a 2 s . c o m*/ String label; String label2; String name = null, code = null; update = new URL("https://sites.google.com/site/mtgfamiliar/manifests/TCGnames.json"); InputStreamReader isr = new InputStreamReader(update.openStream(), "ISO-8859-1"); JsonReader reader = new JsonReader(isr); reader.beginObject(); while (reader.hasNext()) { label = reader.nextName(); if (label.equals("Date")) { String lastUpdate = prefAdapter.getLastTCGNameUpdate(); currentTCGNamePatchDate = reader.nextString(); if (lastUpdate.equals(currentTCGNamePatchDate) && !reparseDatabase) { reader.close(); return; } } else if (label.equals("Sets")) { reader.beginArray(); while (reader.hasNext()) { reader.beginObject(); while (reader.hasNext()) { label2 = reader.nextName(); if (label2.equals("Code")) { code = reader.nextString(); } else if (label2.equals("TCGName")) { name = reader.nextString(); } } mDbHelper.addTCGname(name, code); reader.endObject(); } reader.endArray(); } } reader.endObject(); reader.close(); }
From source file:com.gelakinetic.mtgfam.helpers.updaters.CardAndSetParser.java
License:Open Source License
/** * If a set has a patch, and doesn't exist in the database, this is called to parse an InputStream of JSON and add * it into the database./*w w w.j av a 2 s. c om*/ * <p/> * The JSON uses single character keys, which is a silly thing I did in the name of compression. The patches are * zipped anyway, so it doesn't matter much, but we're stuck with it. * <p/> * There is some special processing for weird power and toughness too * * @param in An InputStream containing valid JSON * @param progressReporter A percentage progress is reported through this class to be shown in the notification * @param cardsToAdd An array list to place cards before adding to the database * @param setsToAdd An array list to place sets before adding to the database * @throws IOException If something goes wrong with the InputStream, this will be thrown */ public void readCardJsonStream(InputStream in, CardProgressReporter progressReporter, ArrayList<MtgCard> cardsToAdd, ArrayList<MtgSet> setsToAdd) throws IOException { JsonReader reader = new JsonReader(new InputStreamReader(in, "ISO-8859-1")); /* Three levels of strings for parsing nested JSON */ String s, s1, s2; String pouTouStr; int numTotalElements = 0; int elementsParsed = 0; reader.beginObject(); reader.nextName(); reader.beginObject(); while (reader.hasNext()) { s = reader.nextName(); if (s.equalsIgnoreCase("v")) { /* bdd_date */ reader.skipValue(); } if (s.equalsIgnoreCase("u")) { /* bdd_version */ reader.skipValue(); } if (s.equalsIgnoreCase("s")) { /* sets */ reader.beginObject(); while (reader.hasNext()) { s1 = reader.nextName(); if (s1.equalsIgnoreCase("b")) { /* set */ MtgSet set; JsonToken jt = reader.peek(); if (jt.equals(JsonToken.BEGIN_OBJECT)) { set = new MtgSet(); reader.beginObject(); while (reader.hasNext()) { s2 = reader.nextName(); if (s2.equalsIgnoreCase("a")) { /* name */ set.name = reader.nextString(); } if (s2.equalsIgnoreCase("r")) { /* code_magicCards */ set.codeMagicCards = reader.nextString(); } if (s2.equalsIgnoreCase("q")) { /* code */ set.code = reader.nextString(); } if (s2.equalsIgnoreCase("y")) { /* date */ set.date = reader.nextLong(); } } setsToAdd.add(set); reader.endObject(); } else if (jt.equals(JsonToken.BEGIN_ARRAY)) { reader.beginArray(); while (reader.hasNext()) { set = new MtgSet(); reader.beginObject(); while (reader.hasNext()) { s2 = reader.nextName(); if (s2.equalsIgnoreCase("a")) { /* name */ set.name = reader.nextString(); } if (s2.equalsIgnoreCase("r")) { /* code_magicCards */ set.codeMagicCards = reader.nextString(); } if (s2.equalsIgnoreCase("q")) { /* code */ set.code = reader.nextString(); } if (s2.equalsIgnoreCase("y")) { /* date */ set.date = reader.nextLong(); } } setsToAdd.add(set); reader.endObject(); } reader.endArray(); } } } reader.endObject(); } if (s.equalsIgnoreCase("p")) { /* cards */ reader.beginObject(); while (reader.hasNext()) { s1 = reader.nextName(); if (s1.equalsIgnoreCase("o")) { /* card */ MtgCard c; reader.beginArray(); while (reader.hasNext()) { reader.beginObject(); c = new MtgCard(); while (reader.hasNext()) { s2 = reader.nextName(); if (s2.equalsIgnoreCase("a")) { /* name */ c.name = reader.nextString(); } else if (s2.equalsIgnoreCase("b")) { /* set */ c.set = reader.nextString(); } else if (s2.equalsIgnoreCase("c")) { /* type */ c.type = reader.nextString(); } else if (s2.equalsIgnoreCase("d")) { /* rarity */ c.rarity = reader.nextString().charAt(0); } else if (s2.equalsIgnoreCase("e")) { /* manaCost */ c.manaCost = reader.nextString(); } else if (s2.equalsIgnoreCase("f")) { /* converted_manaCost */ try { c.cmc = reader.nextInt(); } catch (NumberFormatException e) { reader.skipValue(); } } else if (s2.equalsIgnoreCase("g")) { /* power */ pouTouStr = reader.nextString(); try { c.power = Integer.parseInt(pouTouStr); } catch (NumberFormatException e) { switch (pouTouStr) { case "*": c.power = CardDbAdapter.STAR; break; case "1+*": c.power = CardDbAdapter.ONE_PLUS_STAR; break; case "2+*": c.power = CardDbAdapter.TWO_PLUS_STAR; break; case "7-*": c.power = CardDbAdapter.SEVEN_MINUS_STAR; break; case "*{^2}": c.power = CardDbAdapter.STAR_SQUARED; break; case "{1/2}": c.power = 0.5f; break; case "1{1/2}": c.power = 1.5f; break; case "2{1/2}": c.power = 2.5f; break; case "3{1/2}": c.power = 3.5f; break; } } } else if (s2.equalsIgnoreCase("h")) { /* toughness */ pouTouStr = reader.nextString(); try { c.toughness = Integer.parseInt(pouTouStr); } catch (NumberFormatException e) { switch (pouTouStr) { case "*": c.toughness = CardDbAdapter.STAR; break; case "1+*": c.toughness = CardDbAdapter.ONE_PLUS_STAR; break; case "2+*": c.toughness = CardDbAdapter.TWO_PLUS_STAR; break; case "7-*": c.toughness = CardDbAdapter.SEVEN_MINUS_STAR; break; case "*{^2}": c.toughness = CardDbAdapter.STAR_SQUARED; break; case "{1/2}": c.toughness = 0.5f; break; case "1{1/2}": c.toughness = 1.5f; break; case "2{1/2}": c.toughness = 2.5f; break; case "3{1/2}": c.toughness = 3.5f; break; } } } else if (s2.equalsIgnoreCase("i")) { /* loyalty */ try { c.loyalty = reader.nextInt(); } catch (NumberFormatException e) { reader.skipValue(); } } else if (s2.equalsIgnoreCase("j")) { /* ability */ c.ability = reader.nextString(); } else if (s2.equalsIgnoreCase("k")) { /* flavor */ c.flavor = reader.nextString(); } else if (s2.equalsIgnoreCase("l")) { /* artist */ c.artist = reader.nextString(); } else if (s2.equalsIgnoreCase("m")) { /* number */ c.number = reader.nextString(); } else if (s2.equalsIgnoreCase("n")) { /* color */ c.color = reader.nextString(); } else if (s2.equalsIgnoreCase("x")) { /* multiverse id */ try { c.multiverseId = reader.nextInt(); } catch (NumberFormatException e) { reader.skipValue(); } } } cardsToAdd.add(c); elementsParsed++; progressReporter.reportJsonCardProgress( (int) Math.round(100 * elementsParsed / (double) numTotalElements)); reader.endObject(); } reader.endArray(); } } reader.endObject(); } if (s.equalsIgnoreCase("w")) { /* num_cards */ try { numTotalElements = reader.nextInt(); } catch (NumberFormatException e) { reader.skipValue(); } } } reader.endObject(); reader.close(); }
From source file:com.gelakinetic.mtgfam.helpers.updaters.CardAndSetParser.java
License:Open Source License
/** * This method checks the hardcoded URL and downloads a list of patches to be checked * * @param prefAdapter The preference adapter is used to get the last update time * @return An ArrayList of String[] which contains the {Name, URL, Set Code} for each available patch * @throws IOException Thrown if something goes wrong with the InputStream from the web */// www . ja va2 s.com public ArrayList<String[]> readUpdateJsonStream(PreferenceAdapter prefAdapter) throws IOException { ArrayList<String[]> patchInfo = new ArrayList<>(); URL update; String label; String label2; update = new URL(PATCHES_URL); InputStreamReader isr = new InputStreamReader(update.openStream(), "ISO-8859-1"); JsonReader reader = new JsonReader(isr); reader.beginObject(); while (reader.hasNext()) { label = reader.nextName(); if (label.equals("Date")) { String lastUpdate = prefAdapter.getLastUpdate(); mCurrentPatchDate = reader.nextString(); if (lastUpdate.equals(mCurrentPatchDate)) { reader.close(); return null; } } else if (label.equals("Patches")) { reader.beginArray(); while (reader.hasNext()) { reader.beginObject(); String[] setData = new String[3]; while (reader.hasNext()) { label2 = reader.nextName(); switch (label2) { case "Name": setData[SET_NAME] = reader.nextString(); break; case "URL": setData[SET_URL] = reader.nextString(); break; case "Code": setData[SET_CODE] = reader.nextString(); break; } } patchInfo.add(setData); reader.endObject(); } reader.endArray(); } } reader.endObject(); reader.close(); return patchInfo; }