【发布时间】:2015-06-26 18:21:31
【问题描述】:
我正在使用以下代码以 JSON 响应的形式从 Twitter4j 搜索 API 接收推文。我收到的结果是以列表形式在 Twitter4j 搜索 API 中指定的行
List<Status> tweets = result.getTweets();
问题是推文以列表形式返回,其中一个状态条目具有非空和非空地理位置,而另一个状态条目具有空或空地理位置。因为要从每个状态条目(即 Tweet)中检索相关字段,所以我遍历列表并调用 getter,这对于 GeoLocation 字段为空的状态条目来说是空的。
我尝试遵循的方法:
我创建了一个 POJO TweetJSON_2(在帖子底部定义),其中包含相关字段及其 getter 和 setter。我正在使用 Jackson ObjectMapper 来处理空值,如下所示:
JsonGenerator generator = new JsonFactory().createGenerator(os);
generator.setPrettyPrinter(new DefaultPrettyPrinter());
TweetJSON_2 rawJSON;
ObjectMapper mapper = new ObjectMapper();
//mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
mapper.setSerializationInclusion(Include.NON_NULL);
// ... rawJSON is populated ...
mapper.writeValue(generator, rawJSON);
但是,当我尝试从 Status 中获取 geoLocation 字段时,使用下面标有 ** 的行
List<Status> tweets = result.getTweets();
我得到的 Java NullPointerException 如下:
[Mon Apr 20 11:32:47 IST 2015]{"statuses":[{"retweeted_status":{"contributors":null,"text":"<my text>",**"geo":null**,"retweeted":false,"in_reply_to_screen_name":null,"truncated":false,"lang":"en","entities":{"symbols":[],"urls":[],"hashtags": ... &include_entities=1","since_id_str":"0","completed_in":0.029}}
**Exception in thread "main" java.lang.NullPointerException
at analytics.search.twitter.SearchFieldsTweetsJSON_2.main(SearchFieldsTweetsJSON_2.java:78)**
例如:如果我输入一个json字符串为
String s = "{\"first\": 123, \"second\": [{\"second_first\":null, \"second_second\":null}, {\"second_third\":null}, null], \"third\": 789, \"fourth\":null}";
输出应该是这样的
"{\"first\": 123, \"third\": 789}";
我想要的是替换 JSONArrays 中的所有 null 元素和 JSONObjects 中的所有 null 键值对,无论它们嵌套在我的 JSON 响应中的任何级别。
对象与树模型方法
我尝试了对象模型解析机制,它是一个基于 javax.json.stream.JsonParser.Event 的方法,但需要对 JSON 字符串进行多次访问和对象替换,具体取决于 null 嵌套在哪个级别上非常复杂。同时,如果我使用树模型机制,整个 JSON 响应必须存储为树,这可能会溢出我的 JVM 堆内存,因为根据我的查询参数,JSON 大小可能非常大。我需要找到一个可行的解决方案来克服这个问题。任何有关解决上述问题的建议都将受到高度赞赏。
代码如下:
public class SearchFieldsTweetsJSON_2 {
/* Searches specific fields from Tweets in JSON format */
public static void main(String[] args) throws FileNotFoundException, IOException {
if (args.length < 2) {
System.out.println("java twitter4j.examples.search.SearchTweets [query][outputJSONFile]");
System.exit(-1);
}
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true)
.setOAuthConsumerKey("XXXXXXXXXXXXXXXXXXXXXXXXXX")
.setOAuthConsumerSecret("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
.setOAuthAccessToken("NNNNNNNNN-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
.setOAuthAccessTokenSecret("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
.setJSONStoreEnabled(true);
Twitter twitter = new TwitterFactory(cb.build()).getInstance();
try {
Query query = new Query(args[0]);
QueryResult result;
File jsonFile = new File(args[1]);
System.out.println("File Path : " + jsonFile.getAbsolutePath());
OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(jsonFile));
JsonGenerator generator = new JsonFactory().createGenerator(os);
generator.setPrettyPrinter(new DefaultPrettyPrinter());
TweetJSON_2 rawJSON;
ObjectMapper mapper = new ObjectMapper();
//mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
mapper.setSerializationInclusion(Include.NON_NULL);
do {
result = twitter.search(query);
List<Status> tweets = result.getTweets();
for (Status tweet : tweets) {
rawJSON = new TweetJSON_2();
rawJSON.setStatusId(Long.toString(tweet.getId()));
rawJSON.setUserId(Long.toString(tweet.getUser().getId()));
rawJSON.setUserName(tweet.getUser().getScreenName());
rawJSON.setStatusText(tweet.getText());
rawJSON.setGeoLocation(tweet.getGeoLocation().toString()); **<< Giving error at tweet.getGeoLocation() since GeoLocation is null**
mapper.writeValue(generator, rawJSON);
System.out.println(rawJSON.toString());
}
} while ((query = result.nextQuery()) != null);
generator.close();
System.out.println(os.toString());
} catch (TwitterException te) {
te.printStackTrace();
System.out.println("Failed to search tweets : " + te.getMessage());
System.exit(-1);
}
}
}
我已按如下方式定义了我的 TweetJSON_2 Java 对象:
public class TweetJSON_2 {
public String statusId;
public String statusText;
public String userId;
public String userName;
public String geoLocation;
public String getStatusId() {
return statusId;
}
public void setStatusId(String statusId) {
this.statusId = statusId;
}
public String getStatusText() {
return statusText;
}
public void setStatusText(String statusText) {
this.statusText = statusText;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getGeoLocation() {
return geoLocation;
}
public void setGeoLocation(String geoLocation) {
this.geoLocation = geoLocation;
}
@Override
public String toString() {
return "TweetJSON_2 [ statusId = " + statusId + ", statusText = " + statusText + "]";
}
}
【问题讨论】:
标签: json serialization jackson twitter4j pojo