Repository: asterixdb Updated Branches: refs/heads/master 1be612a8e -> 46518babd
Fix uniontype compatibility issue in TweetParser 1. Fix compatibility issue of UnionType in TweetParser. 2. Add unit test for TweetParser, covering missing attribute record filtering. Change-Id: Id7e316d20f929236b3fa17618bb8f87d28ac7efc Reviewed-on: https://asterix-gerrit.ics.uci.edu/1786 Tested-by: Jenkins <[email protected]> BAD: Jenkins <[email protected]> Integration-Tests: Jenkins <[email protected]> Reviewed-by: Steven Jacobs <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/asterixdb/repo Commit: http://git-wip-us.apache.org/repos/asf/asterixdb/commit/46518bab Tree: http://git-wip-us.apache.org/repos/asf/asterixdb/tree/46518bab Diff: http://git-wip-us.apache.org/repos/asf/asterixdb/diff/46518bab Branch: refs/heads/master Commit: 46518babd57147b66c4016cea520687ccfaf60c1 Parents: 1be612a Author: Xikui Wang <[email protected]> Authored: Mon May 29 22:55:51 2017 -0700 Committer: Xikui Wang <[email protected]> Committed: Fri Jun 2 14:25:37 2017 -0700 ---------------------------------------------------------------------- asterixdb/asterix-external-data/pom.xml | 1 + .../asterix/external/parser/TweetParser.java | 45 +++++--- .../external/parser/test/TweetParserTest.java | 109 +++++++++++++++++++ .../src/test/resources/test_tweets.txt | 6 + 4 files changed, 145 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/asterixdb/blob/46518bab/asterixdb/asterix-external-data/pom.xml ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-external-data/pom.xml b/asterixdb/asterix-external-data/pom.xml index ff9fcb0..460f57d 100644 --- a/asterixdb/asterix-external-data/pom.xml +++ b/asterixdb/asterix-external-data/pom.xml @@ -170,6 +170,7 @@ <exclude>src/test/resources/classad/**</exclude> <!-- HTCondor (license in LICENSE file) --> <exclude>src/test/resources/record.json</exclude> <!-- https://issues.apache.org/jira/browse/ASTERIXDB-1850 --> <exclude>src/test/resources/change_feed.csv</exclude> + <exclude>src/test/resources/test_tweets.txt</exclude> </excludes> </configuration> </plugin> http://git-wip-us.apache.org/repos/asf/asterixdb/blob/46518bab/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/TweetParser.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/TweetParser.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/TweetParser.java index 1b29c887..be49863 100644 --- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/TweetParser.java +++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/TweetParser.java @@ -24,16 +24,16 @@ import org.apache.asterix.builders.AbvsBuilderFactory; import org.apache.asterix.builders.IARecordBuilder; import org.apache.asterix.builders.IAsterixListBuilder; import org.apache.asterix.builders.ListBuilderFactory; +import org.apache.asterix.builders.OrderedListBuilder; import org.apache.asterix.builders.RecordBuilderFactory; -import org.apache.asterix.builders.UnorderedListBuilder; import org.apache.asterix.common.exceptions.ErrorCode; import org.apache.asterix.common.exceptions.RuntimeDataException; import org.apache.asterix.external.api.IRawRecord; import org.apache.asterix.external.api.IRecordDataParser; -import org.apache.asterix.om.base.AMutablePoint; import org.apache.asterix.om.base.ANull; import org.apache.asterix.om.types.ARecordType; import org.apache.asterix.om.types.ATypeTag; +import org.apache.asterix.om.types.AUnionType; import org.apache.asterix.om.types.BuiltinType; import org.apache.asterix.om.types.IAType; import org.apache.asterix.om.util.container.IObjectPool; @@ -59,25 +59,28 @@ public class TweetParser extends AbstractDataParser implements IRecordDataParser public TweetParser(ARecordType recordType) { this.recordType = recordType; - aPoint = new AMutablePoint(0, 0); } - private void parseUnorderedList(JsonNode jArray, DataOutput output) throws IOException { + private void parseArrayList(JsonNode jArray, DataOutput output) throws IOException { ArrayBackedValueStorage itemBuffer = getTempBuffer(); - UnorderedListBuilder unorderedListBuilder = (UnorderedListBuilder) getUnorderedListBuilder(); + OrderedListBuilder arrayBuilder = (OrderedListBuilder) getArrayBuilder(); - unorderedListBuilder.reset(null); + arrayBuilder.reset(null); for (int iter1 = 0; iter1 < jArray.size(); iter1++) { itemBuffer.reset(); if (writeField(jArray.get(iter1), null, itemBuffer.getDataOutput())) { - unorderedListBuilder.addItem(itemBuffer); + arrayBuilder.addItem(itemBuffer); } } - unorderedListBuilder.write(output, true); + arrayBuilder.write(output, true); } - private boolean writeField(JsonNode fieldObj, IAType fieldType, DataOutput out) throws IOException { + private boolean writeField(JsonNode fieldObj, IAType originalFieldType, DataOutput out) throws IOException { boolean writeResult = true; + IAType fieldType = originalFieldType; + if (originalFieldType instanceof AUnionType) { + fieldType = ((AUnionType) originalFieldType).getActualType(); + } if (fieldType != null) { switch (fieldType.getTypeTag()) { case STRING: @@ -103,6 +106,9 @@ public class TweetParser extends AbstractDataParser implements IRecordDataParser case OBJECT: writeRecord(fieldObj, out, (ARecordType) fieldType); break; + case ARRAY: + parseArrayList(fieldObj, out); + break; default: writeResult = false; } @@ -126,7 +132,7 @@ public class TweetParser extends AbstractDataParser implements IRecordDataParser utf8Writer.writeUTF8(fieldObj.asText(), out); } else if (fieldObj.isArray()) { if ((fieldObj).size() != 0) { - parseUnorderedList(fieldObj, out); + parseArrayList(fieldObj, out); } else { writeResult = false; } @@ -159,6 +165,7 @@ public class TweetParser extends AbstractDataParser implements IRecordDataParser String[] curFNames = null; int fieldN; int attrIdx; + int expectedFieldsCount = 0; ArrayBackedValueStorage fieldValueBuffer = getTempBuffer(); ArrayBackedValueStorage fieldNameBuffer = getTempBuffer(); @@ -167,6 +174,11 @@ public class TweetParser extends AbstractDataParser implements IRecordDataParser if (curRecType != null) { curTypes = curRecType.getFieldTypes(); curFNames = curRecType.getFieldNames(); + for (IAType curType : curTypes) { + if (!(curType instanceof AUnionType)) { + expectedFieldsCount++; + } + } } recBuilder.reset(curRecType); @@ -178,10 +190,11 @@ public class TweetParser extends AbstractDataParser implements IRecordDataParser for (int iter1 = 0; iter1 < fieldN; iter1++) { fieldValueBuffer.reset(); DataOutput fieldOutput = fieldValueBuffer.getDataOutput(); - if (obj.get(curFNames[iter1]).isNull()) { + if (obj.get(curFNames[iter1]).isNull() && !(curTypes[iter1] instanceof AUnionType)) { if (curRecType.isClosedField(curFNames[iter1])) { throw new RuntimeDataException(ErrorCode.PARSER_TWEET_PARSER_CLOSED_FIELD_NULL, - curFNames[iter1]); } else { + curFNames[iter1]); + } else { continue; } } else { @@ -198,7 +211,7 @@ public class TweetParser extends AbstractDataParser implements IRecordDataParser Iterator<String> iter = obj.fieldNames(); while (iter.hasNext()) { attrName = iter.next(); - if (obj.get(attrName).isNull() || obj.size() == 0) { + if (obj.get(attrName) == null || obj.get(attrName).isNull() || obj.size() == 0) { continue; } attrIdx = checkAttrNameIdx(curFNames, attrName); @@ -219,7 +232,7 @@ public class TweetParser extends AbstractDataParser implements IRecordDataParser } } } - if (curRecType != null && closedFieldCount < curFNames.length) { + if (curRecType != null && closedFieldCount < expectedFieldsCount) { throw new HyracksDataException("Non-null field is null"); } } @@ -230,8 +243,8 @@ public class TweetParser extends AbstractDataParser implements IRecordDataParser return recordBuilderPool.allocate(ATypeTag.OBJECT); } - private IAsterixListBuilder getUnorderedListBuilder() { - return listBuilderPool.allocate(ATypeTag.MULTISET); + private IAsterixListBuilder getArrayBuilder() { + return listBuilderPool.allocate(ATypeTag.ARRAY); } private ArrayBackedValueStorage getTempBuffer() { http://git-wip-us.apache.org/repos/asf/asterixdb/blob/46518bab/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/parser/test/TweetParserTest.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/parser/test/TweetParserTest.java b/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/parser/test/TweetParserTest.java new file mode 100644 index 0000000..5389310 --- /dev/null +++ b/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/parser/test/TweetParserTest.java @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.asterix.external.parser.test; + +import static org.apache.asterix.om.types.BuiltinType.AFLOAT; +import static org.apache.asterix.om.types.BuiltinType.AINT64; +import static org.apache.asterix.om.types.BuiltinType.AMISSING; +import static org.apache.asterix.om.types.BuiltinType.ANULL; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutput; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +import org.apache.asterix.external.input.record.GenericRecord; +import org.apache.asterix.external.parser.TweetParser; +import org.apache.asterix.om.types.AOrderedListType; +import org.apache.asterix.om.types.ARecordType; +import org.apache.asterix.om.types.AUnionType; +import org.apache.asterix.om.types.IAType; +import org.apache.hyracks.api.exceptions.HyracksDataException; +import org.junit.Assert; +import org.junit.Test; + +import junit.extensions.PA; + +public class TweetParserTest { + + @Test + public void openRecordTypeTest() throws IOException, URISyntaxException { + String[] ids = { "720549057849114629", "668950503552864257", "668945640186101761", "263602997047730177", + "668948268605403136", "741701526859567104" }; + // contruct type + IAType geoFieldType = new ARecordType("GeoType", new String[] { "coordinates" }, + new IAType[] { new AOrderedListType(AFLOAT, "point") }, true); + List<IAType> unionTypeList = new ArrayList<>(); + unionTypeList.add(geoFieldType); + unionTypeList.add(ANULL); + unionTypeList.add(AMISSING); + IAType geoUnionType = new AUnionType(unionTypeList, "GeoType?"); + ARecordType tweetRecordType = new ARecordType("TweetType", new String[] { "id", "geo" }, + new IAType[] { AINT64, geoUnionType }, true); + + TweetParser parser = new TweetParser(tweetRecordType); + + List<String> lines = Files.readAllLines(Paths.get(getClass().getResource("/test_tweets.txt").toURI())); + ByteArrayOutputStream is = new ByteArrayOutputStream(); + DataOutput output = new DataOutputStream(is); + for (int iter1 = 0; iter1 < lines.size(); iter1++) { + GenericRecord<String> record = new GenericRecord<>(); + record.set(lines.get(iter1)); + try { + parser.parse(record, output); + } catch (HyracksDataException e) { + e.printStackTrace(); + Assert.fail("Unexpected failure in parser."); + } + Assert.assertTrue((PA.getValue(parser, "aInt64")).toString().equals(ids[iter1])); + } + } + + @Test + public void closedRecordTypeTest() throws IOException, URISyntaxException { + // contruct type + IAType geoFieldType = new ARecordType("GeoType", new String[] { "coordinates" }, + new IAType[] { new AOrderedListType(AFLOAT, "point") }, true); + ARecordType tweetRecordType = new ARecordType("TweetType", new String[] { "id", "geo" }, + new IAType[] { AINT64, geoFieldType }, true); + + TweetParser parser = new TweetParser(tweetRecordType); + List<String> lines = Files.readAllLines(Paths.get(getClass().getResource("/test_tweets.txt").toURI())); + ByteArrayOutputStream is = new ByteArrayOutputStream(); + DataOutput output = new DataOutputStream(is); + int regularCount = 0; + for (int iter1 = 0; iter1 < lines.size(); iter1++) { + GenericRecord<String> record = new GenericRecord<>(); + record.set(lines.get(iter1)); + try { + parser.parse(record, output); + regularCount++; + } catch (HyracksDataException e) { + Assert.assertTrue(e.toString().contains("Non-null") && (iter1 == 0 || iter1 == 1)); + } + } + Assert.assertTrue(regularCount == 4); + } +} http://git-wip-us.apache.org/repos/asf/asterixdb/blob/46518bab/asterixdb/asterix-external-data/src/test/resources/test_tweets.txt ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-external-data/src/test/resources/test_tweets.txt b/asterixdb/asterix-external-data/src/test/resources/test_tweets.txt new file mode 100644 index 0000000..ed8869a --- /dev/null +++ b/asterixdb/asterix-external-data/src/test/resources/test_tweets.txt @@ -0,0 +1,6 @@ +{"created_at":"Thu Apr 14 09:47:37 +0000 2016","id":720549057849114629,"id_str":"720549057849114629","text":"Pumpins and mother lovin humpins! https:\/\/t.co\/UFY2ptZEDE","source":"\u003ca href=\"http:\/\/twitter.com\/download\/iphone\" rel=\"nofollow\"\u003eTwitter for iPhone\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":22718875,"id_str":"22718875","name":"Austin Ireland","screen_name":"fastirish","location":"GaageBox2.0","url":null,"description":"CrossFit, raising elite offspring and tattoos. O, and tiny dogs!! #garagebox2.0 #unaffiliated","protected":false,"verified":false,"followers_count":206,"friends_count":336,"listed_count":10,"favourites_count":888,"statuses_count":1775,"created_at":"Wed Mar 04 02:14:49 +0000 2009","utc_offset":-14400,"time_zone":"Eastern Time (US & Canada)","geo_enabled":true,"lang":"en","contributors_enab led":false,"is_translator":false,"profile_background_color":"352726","profile_background_image_url":"http:\/\/abs.twimg.com\/images\/themes\/theme5\/bg.gif","profile_background_image_url_https":"https:\/\/abs.twimg.com\/images\/themes\/theme5\/bg.gif","profile_background_tile":false,"profile_link_color":"D02B55","profile_sidebar_border_color":"829D5E","profile_sidebar_fill_color":"99CC33","profile_text_color":"3E4415","profile_use_background_image":true,"profile_image_url":"http:\/\/pbs.twimg.com\/profile_images\/712092320099868672\/YUUcDgwG_normal.jpg","profile_image_url_https":"https:\/\/pbs.twimg.com\/profile_images\/712092320099868672\/YUUcDgwG_normal.jpg","profile_banner_url":"https:\/\/pbs.twimg.com\/profile_banners\/22718875\/1458315357","default_profile":false,"default_profile_image":false,"following":null,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":{"id":"07d9d0f1fd482001","url":"https:\/\/api.twitter.com\/1.1\/geo\/id\/07d9d0f1fd4 82001.json","place_type":"poi","name":"Steeplechase","full_name":"Steeplechase","country_code":"US","country":"United States","bounding_box":{"type":"Polygon","coordinates":[[[-75.655008,38.355629],[-75.655008,38.355629],[-75.655008,38.355629],[-75.655008,38.355629]]]},"attributes":{}},"contributors":null,"is_quote_status":false,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[],"urls":[],"user_mentions":[],"symbols":[],"media":[{"id":720549047702986752,"id_str":"720549047702986752","indices":[34,57],"media_url":"http:\/\/pbs.twimg.com\/media\/Cf_nio-VIAAd6wB.jpg","media_url_https":"https:\/\/pbs.twimg.com\/media\/Cf_nio-VIAAd6wB.jpg","url":"https:\/\/t.co\/UFY2ptZEDE","display_url":"pic.twitter.com\/UFY2ptZEDE","expanded_url":"http:\/\/twitter.com\/fastirish\/status\/720549057849114629\/photo\/1","type":"photo","sizes":{"small":{"w":340,"h":453,"resize":"fit"},"large":{"w":960,"h":1280,"resize":"fit"},"medium":{"w":600,"h":800,"resize":"fit"},"thumb":{"w":150,"h":150,"r esize":"crop"}}}]},"extended_entities":{"media":[{"id":720549047702986752,"id_str":"720549047702986752","indices":[34,57],"media_url":"http:\/\/pbs.twimg.com\/media\/Cf_nio-VIAAd6wB.jpg","media_url_https":"https:\/\/pbs.twimg.com\/media\/Cf_nio-VIAAd6wB.jpg","url":"https:\/\/t.co\/UFY2ptZEDE","display_url":"pic.twitter.com\/UFY2ptZEDE","expanded_url":"http:\/\/twitter.com\/fastirish\/status\/720549057849114629\/photo\/1","type":"photo","sizes":{"small":{"w":340,"h":453,"resize":"fit"},"large":{"w":960,"h":1280,"resize":"fit"},"medium":{"w":600,"h":800,"resize":"fit"},"thumb":{"w":150,"h":150,"resize":"crop"}}}]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"filter_level":"low","lang":"en","timestamp_ms":"1460627257202"} +{"created_at":"Tue Nov 24 00:33:23 +0000 2015","id":668950503552864257,"id_str":"668950503552864257","text":"@K_Jenkins22 I know it could always be worse, lol I could always be a saints fan \ud83d\ude02","source":"\u003ca href=\"http:\/\/twitter.com\/download\/iphone\" rel=\"nofollow\"\u003eTwitter for iPhone\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":668949646656593920,"in_reply_to_status_id_str":"668949646656593920","in_reply_to_user_id":322358152,"in_reply_to_user_id_str":"322358152","in_reply_to_screen_name":"K_Jenkins22","user":{"id":375920299,"id_str":"375920299","name":"Taylor Casey","screen_name":"TeeCasey11","location":"Louisville Ky","url":null,"description":"I cant drown my demons they know how to swim","protected":false,"verified":false,"followers_count":614,"friends_count":327,"listed_count":1,"favourites_count":1518,"statuses_count":25058,"created_at":"Mon Sep 19 00:06:07 +0000 2011","utc_offset":-21600,"time_zone":"Central Time (US & Canada)","geo_enabl ed":true,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"C0DEED","profile_background_image_url":"http:\/\/abs.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_image_url_https":"https:\/\/abs.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_tile":false,"profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"profile_image_url":"http:\/\/pbs.twimg.com\/profile_images\/650694639981363200\/baMfTh4z_normal.jpg","profile_image_url_https":"https:\/\/pbs.twimg.com\/profile_images\/650694639981363200\/baMfTh4z_normal.jpg","profile_banner_url":"https:\/\/pbs.twimg.com\/profile_banners\/375920299\/1395204592","default_profile":true,"default_profile_image":false,"following":null,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":{"id":"000df0c11a2783f2","url":"https:\/\/api .twitter.com\/1.1\/geo\/id\/000df0c11a2783f2.json","place_type":"city","name":"Hillview","full_name":"Hillview, KY","country_code":"US","country":"United States","bounding_box":{"type":"Polygon","coordinates":[[[-85.710047,38.029300],[-85.710047,38.086251],[-85.608063,38.086251],[-85.608063,38.029300]]]},"attributes":{}},"contributors":null,"is_quote_status":false,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[],"urls":[],"user_mentions":[{"screen_name":"K_Jenkins22","name":"Kirsty Jenkins","id":322358152,"id_str":"322358152","indices":[0,12]}],"symbols":[]},"favorited":false,"retweeted":false,"filter_level":"low","lang":"en","timestamp_ms":"1448325203203"} +{"created_at":"Tue Nov 24 00:14:03 +0000 2015","id":668945640186101761,"id_str":"668945640186101761","text":"Just posted a photo @ Campus Martius Park https:\/\/t.co\/5Ax4E2CdWZ","source":"\u003ca href=\"http:\/\/instagram.com\" rel=\"nofollow\"\u003eInstagram\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":48121888,"id_str":"48121888","name":"Kevin McKague","screen_name":"KevinOfMI","location":"Davison, Michigan","url":"http:\/\/KevinMcKague.wordpress.com","description":"I need to ride my bike until my brain shuts up and my muscles are screaming.\u00a0\nRight after these donuts. Dad of 3.\n Visit my blog 18 Wheels and a 12-Speed Bike.","protected":false,"verified":false,"followers_count":1178,"friends_count":1780,"listed_count":50,"favourites_count":2319,"statuses_count":22263,"created_at":"Wed Jun 17 21:24:03 +0000 2009","utc_offset" :-18000,"time_zone":"Eastern Time (US & Canada)","geo_enabled":true,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"EBF5ED","profile_background_image_url":"http:\/\/pbs.twimg.com\/profile_background_images\/378800000153875492\/VrUNrXXF.jpeg","profile_background_image_url_https":"https:\/\/pbs.twimg.com\/profile_background_images\/378800000153875492\/VrUNrXXF.jpeg","profile_background_tile":true,"profile_link_color":"0084B4","profile_sidebar_border_color":"FFFFFF","profile_sidebar_fill_color":"DDFFCC","profile_text_color":"333333","profile_use_background_image":true,"profile_image_url":"http:\/\/pbs.twimg.com\/profile_images\/646097130977890304\/izCl0tCD_normal.jpg","profile_image_url_https":"https:\/\/pbs.twimg.com\/profile_images\/646097130977890304\/izCl0tCD_normal.jpg","profile_banner_url":"https:\/\/pbs.twimg.com\/profile_banners\/48121888\/1441581344","default_profile":false,"default_profile_image":false,"following":null,"follow_reques t_sent":null,"notifications":null},"geo":{"type":"Point","coordinates":[42.33170228,-83.04647491]},"coordinates":{"type":"Point","coordinates":[-83.04647491,42.33170228]},"place":{"id":"b463d3bd6064861b","url":"https:\/\/api.twitter.com\/1.1\/geo\/id\/b463d3bd6064861b.json","place_type":"city","name":"Detroit","full_name":"Detroit, MI","country_code":"US","country":"United States","bounding_box":{"type":"Polygon","coordinates":[[[-83.288056,42.255085],[-83.288056,42.450488],[-82.910520,42.450488],[-82.910520,42.255085]]]},"attributes":{}},"contributors":null,"is_quote_status":false,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[],"urls":[{"url":"https:\/\/t.co\/5Ax4E2CdWZ","expanded_url":"https:\/\/instagram.com\/p\/-cnH0kFL_g\/","display_url":"instagram.com\/p\/-cnH0kFL_g\/","indices":[42,65]}],"user_mentions":[],"symbols":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"filter_level":"low","lang":"en","timestamp_ms":"1448324043686"} +{"contributors":null,"text":"@Thaynalhul qosjaosjoa e tu nem viu","geo":{"type":"Point","coordinates":[-29.9460537,-50.99058655]},"retweeted":false,"in_reply_to_screen_name":"Thaynalhul","truncated":false,"entities":{"urls":[],"hashtags":[],"user_mentions":[{"id":157459005,"name":"Thayná Lhul","indices":[0,11],"screen_name":"Thaynalhul","id_str":"157459005"}]},"in_reply_to_status_id_str":"263602825592979456","id":263602997047730177,"in_reply_to_user_id_str":"157459005","source":"<a href=\"http://twitter.com/download/iphone\" rel=\"nofollow\">Twitter for iPhone<\/a>","favorited":false,"in_reply_to_status_id":263602825592979456,"in_reply_to_user_id":157459005,"retweet_count":0,"created_at":"Wed Oct 31 11:27:06 +0000 2012","id_str":"263602997047730177","place":{"id":"66a72011ed6d4853","bounding_box":{"type":"Polygon","coordinates":[[[-51.1012029,-30.0156525],[-50.8114625,-30.0156525],[-50.8114625,-29.765777],[-51.1012029,-29.765777]]]},"place_type":"city","name":"GravataÃ","attribute s":{},"country_code":"BR","url":"http://api.twitter.com/1/geo/id/66a72011ed6d4853.json","full_name":"GravataÃ, Rio Grande do Sul","country":"Brasil"},"user":{"location":"","default_profile":false,"profile_background_tile":true,"statuses_count":26476,"lang":"pt","profile_link_color":"0099CC","profile_banner_url":"https://si0.twimg.com/profile_banners/338399662/1351549264","id":338399662,"following":null,"protected":false,"favourites_count":247,"profile_text_color":"333333","contributors_enabled":false,"verified":false,"description":"\u201cPorque a vida só dá pra quem se deu, pra quem amou, pra quem chorou, pra quem sofreu.\u201d #Belieber ","name":"beatriz ","profile_sidebar_border_color":"fff","profile_background_color":"FFF04D","created_at":"Tue Jul 19 14:39:45 +0000 2011","default_profile_image":false,"followers_count":998,"profile_image_url_https":"https://si0.twimg.com/profile_images/2778405459/f682a9eadbbe5ed9bc37c9e8e5a1d33b_normal.jpeg","geo_enabled":true,"profile_backgrou nd_image_url":"http://a0.twimg.com/profile_background_images/697292787/7156609856becbed318bffd052449fc8.jpeg","profile_background_image_url_https":"https://si0.twimg.com/profile_background_images/697292787/7156609856becbed318bffd052449fc8.jpeg","follow_request_sent":null,"url":"http://ask.fm/soudaviuscka","utc_offset":-14400,"time_zone":"Santiago","notifications":null,"profile_use_background_image":true,"friends_count":277,"profile_sidebar_fill_color":"E6F6F9","screen_name":"bewexell","id_str":"338399662","profile_image_url":"http://a0.twimg.com/profile_images/2778405459/f682a9eadbbe5ed9bc37c9e8e5a1d33b_normal.jpeg","is_translator":false,"listed_count":3},"coordinates":{"type":"Point","coordinates":[-50.99058655,-29.9460537]}} +{"created_at":"Tue Nov 24 00:24:30 +0000 2015","id":668948268605403136,"id_str":"668948268605403136","text":"\u26a1\ufe0fFeed me energy, I'll feed it back\/Spread love\/ Be the energy. It's more to opening your eyes. After\u2026 https:\/\/t.co\/SYWXANPYxI","source":"\u003ca href=\"http:\/\/instagram.com\" rel=\"nofollow\"\u003eInstagram\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":35392759,"id_str":"35392759","name":"See-Oh-Be-Uh","screen_name":"ItsSeobia","location":"Exploring","url":null,"description":"Lifestyle over everything. We might take a break, but we don't quit. #Active #MovementSpeaksLouderThanYourTweets #EarnYourStripes","protected":false,"verified":false,"followers_count":951,"friends_count":471,"listed_count":28,"favourites_count":690,"statuses_count":49387,"created_at":"Sun Apr 26 03:38:50 +0000 2009","utc_offset":-21 600,"time_zone":"Central Time (US & Canada)","geo_enabled":true,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"A336F7","profile_background_image_url":"http:\/\/pbs.twimg.com\/profile_background_images\/215051616\/purple_flower.jpg","profile_background_image_url_https":"https:\/\/pbs.twimg.com\/profile_background_images\/215051616\/purple_flower.jpg","profile_background_tile":true,"profile_link_color":"05FF22","profile_sidebar_border_color":"099FF0","profile_sidebar_fill_color":"030003","profile_text_color":"8911B8","profile_use_background_image":true,"profile_image_url":"http:\/\/pbs.twimg.com\/profile_images\/574735896752308225\/EDeXr2-5_normal.png","profile_image_url_https":"https:\/\/pbs.twimg.com\/profile_images\/574735896752308225\/EDeXr2-5_normal.png","profile_banner_url":"https:\/\/pbs.twimg.com\/profile_banners\/35392759\/1428866329","default_profile":false,"default_profile_image":false,"following":null,"follow_request_sent":null," notifications":null},"geo":{"type":"Point","coordinates":[41.8,-87.59]},"coordinates":{"type":"Point","coordinates":[-87.59,41.8]},"contributors":null,"is_quote_status":false,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[],"urls":[{"url":"https:\/\/t.co\/SYWXANPYxI","expanded_url":"https:\/\/instagram.com\/p\/-coUG4GMYI\/","display_url":"instagram.com\/p\/-coUG4GMYI\/","indices":[103,126]}],"user_mentions":[],"symbols":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"filter_level":"low","lang":"en","timestamp_ms":"1448324670350"} +{"created_at":"Sat Jun 11 18:39:58 +0000 2016","id":741701526859567104,"id_str":"741701526859567104","text":"Jazz Age Lawn Party #jalp2016 #governorsisland @ Governors Island https:\/\/t.co\/kj4dLzdngB","source":"\u003ca href=\"http:\/\/instagram.com\" rel=\"nofollow\"\u003eInstagram\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":17816081,"id_str":"17816081","name":"Paul Herrera","screen_name":"pherrera","location":"New York, NY","url":"http:\/\/www.pherrera.com","description":"The Michael Jordan of something","protected":false,"verified":false,"followers_count":479,"friends_count":443,"listed_count":36,"favourites_count":40,"statuses_count":12911,"created_at":"Tue Dec 02 19:36:06 +0000 2008","utc_offset":-14400,"time_zone":"Eastern Time (US & Canada)","geo_enabled":true,"lang":"en","contributors_enabled":false,"is_translator":false," profile_background_color":"352726","profile_background_image_url":"http:\/\/abs.twimg.com\/images\/themes\/theme5\/bg.gif","profile_background_image_url_https":"https:\/\/abs.twimg.com\/images\/themes\/theme5\/bg.gif","profile_background_tile":false,"profile_link_color":"D02B55","profile_sidebar_border_color":"829D5E","profile_sidebar_fill_color":"99CC33","profile_text_color":"3E4415","profile_use_background_image":true,"profile_image_url":"http:\/\/pbs.twimg.com\/profile_images\/719606026153144321\/JrfcfLdP_normal.jpg","profile_image_url_https":"https:\/\/pbs.twimg.com\/profile_images\/719606026153144321\/JrfcfLdP_normal.jpg","profile_banner_url":"https:\/\/pbs.twimg.com\/profile_banners\/17816081\/1354488949","default_profile":false,"default_profile_image":false,"following":null,"follow_request_sent":null,"notifications":null},"geo":{"type":"Point","coordinates":[40.69138889,-74.01611111]},"coordinates":{"type":"Point","coordinates":[-74.01611111,40.69138889]},"place":{"id":"01a9a 39529b27f36","url":"https:\/\/api.twitter.com\/1.1\/geo\/id\/01a9a39529b27f36.json","place_type":"city","name":"Manhattan","full_name":"Manhattan, NY","country_code":"US","country":"United States","bounding_box":{"type":"Polygon","coordinates":[[[-74.026675,40.683935],[-74.026675,40.877483],[-73.910408,40.877483],[-73.910408,40.683935]]]},"attributes":{}},"contributors":null,"is_quote_status":false,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[{"text":"jalp2016","indices":[20,29]},{"text":"governorsisland","indices":[30,46]}],"urls":[{"url":"https:\/\/t.co\/kj4dLzdngB","expanded_url":"https:\/\/www.instagram.com\/p\/BGhkqneIg8O\/","display_url":"instagram.com\/p\/BGhkqneIg8O\/","indices":[66,89]}],"user_mentions":[],"symbols":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"filter_level":"low","lang":"en","timestamp_ms":"1465670398808"} \ No newline at end of file
