0

我有一个桌面应用程序,它读取 Facebook 消息(FQL 术语中的 unified_message),它由其他用户留在我的 Facebook 页面上。问题是:当用户编写包含链接的消息时,Facebook 会自动将一些对象附加到消息中。这个附件在 RestFb Lib 中导致异常。不幸的是,我的页面访问令牌无济于事,因为您必须在 Facebook 中以我的身份登录才能使用它。但场景很简单,尝试在“www.wheather.com - 酷网站”之类的页面上留言。我已经用 RestFb 1.6.9 和 1.6.11 进行了尝试——两者的结果相同。抱歉格式化。我不能以其他方式做到这一点:(

这是 1.6.11 的堆栈:

com.restfb.exception.FacebookJsonMappingException: Unable to convert Facebook response JSON to a list of java.lang.String instances.  Offending JSON is {"38d79791ef0dac6f0b645a87f4d152d7":{"icon":"https://fbstatic-a.akamaihd.net/rsrc.php/v2/yD/r/aS8ecmYRys0.gif","fb_object_type":"","tagged_ids":[],"description":"The Weather Channel and weather.com provide a national and local weather forecast for cities, as well as weather radar, report and hurricane coverage.","name":"National and Local Weather Forecast, Hurricane, Radar and Report","fb_object_id":"","caption":"www.weather.com","properties":[],"media":[],"href":"http://www.weather.com/"}}
    at com.restfb.DefaultJsonMapper.toJavaList(DefaultJsonMapper.java:171)
    at com.restfb.DefaultJsonMapper.toJavaType(DefaultJsonMapper.java:653)
    at com.restfb.DefaultJsonMapper.toJavaObject(DefaultJsonMapper.java:290)
    at com.restfb.DefaultJsonMapper.toJavaList(DefaultJsonMapper.java:181)
    at com.restfb.DefaultJsonMapper.toJavaType(DefaultJsonMapper.java:653)
    at com.restfb.DefaultJsonMapper.toJavaObject(DefaultJsonMapper.java:290)
       at myprogram.MyDefaultFacebokClient.executeMultiquery(MyDefaultFacebokClient.java:62)
Caused by: com.restfb.json.JsonException: JsonObject["data"] not found.
    at com.restfb.json.JsonObject.get(JsonObject.java:525)
    at com.restfb.DefaultJsonMapper.toJavaList(DefaultJsonMapper.java:155)
    ... 17 more

这是 1.6.9 的堆栈:

com.restfb.exception.FacebookJsonMappingException: Unable to convert Facebook response JSON to a list of java.lang.String instances.  Offending JSON is {"38d79791ef0dac6f0b645a87f4d152d7":{"icon":"https://fbstatic-a.akamaihd.net/rsrc.php/v2/yD/r/aS8ecmYRys0.gif","fb_object_type":"","tagged_ids":[],"description":"The Weather Channel and weather.com provide a national and local weather forecast for cities, as well as weather radar, report and hurricane coverage.","name":"National and Local Weather Forecast, Hurricane, Radar and Report","fb_object_id":"","caption":"www.weather.com","properties":[],"media":[],"href":"http://www.weather.com/"}}
    at com.restfb.DefaultJsonMapper.toJavaList(DefaultJsonMapper.java:167)
    at com.restfb.DefaultJsonMapper.toJavaType(DefaultJsonMapper.java:602)
    at com.restfb.DefaultJsonMapper.toJavaObject(DefaultJsonMapper.java:279)
    at com.restfb.DefaultJsonMapper.toJavaList(DefaultJsonMapper.java:177)
    at com.restfb.DefaultJsonMapper.toJavaType(DefaultJsonMapper.java:602)
    at com.restfb.DefaultJsonMapper.toJavaObject(DefaultJsonMapper.java:279)
       at myprogram.MyDefaultFacebokClient.executeMultiquery(MyDefaultFacebokClient.java:62)
    . . .
Caused by: com.restfb.json.JsonException: JsonObject["data"] not found.
    at com.restfb.json.JsonObject.get(JsonObject.java:525)
    at com.restfb.DefaultJsonMapper.toJavaList(DefaultJsonMapper.java:151)
    ... 17 more

这是 FQL 请求:

{
"users":"SELECT uid,first_name,middle_name,last_name,name,pic_small,pic_big,profile_update_time,timezone,religion,birthday,birthday_date,sex,hometown_location,relationship_status,political,current_location,about_me,notes_count,wall_count,status,locale,profile_url,verified,profile_blurb,username,is_blocked,email,friend_count,languages FROM user WHERE uid IN (SELECT sender FROM #messages)"
,"msg":"SELECT message_id FROM unified_message WHERE thread_id='t_id.238275946308607' AND timestamp > '1360112817564' AND sender.user_id != '507447822604742' LIMIT 100"
,"messages":"SELECT message_id,thread_id,subject,body,unread,action_id,timestamp,tags,sender,recipients,object_sender,html_body,attachments,shares,share_map FROM unified_message WHERE message_id IN (SELECT message_id FROM #msg) AND timestamp > '1360112817564' AND timestamp <= '1360117314920' LIMIT 100"
}

以下是 Facebook Explorer 对上述请求的回复:

{
  "data": [
    {
      "name": "msg", 
      "fql_result_set": [
        {
          "message_id": "m_mid.1360112949050:d17ca4ed7fc6236a75"
        }
      ]
    }, 
    {
      "name": "messages", 
      "fql_result_set": [
        {
          "message_id": "m_mid.1360112949050:d17ca4ed7fc6236a75", 
          "thread_id": "t_id.238275946308607", 
          "subject": null, 
          "body": "Have a look on http://www.weather.com 1", 
          "unread": true, 
          "action_id": "1360112949128000000", 
          "timestamp": "1360112949058", 
          "tags": [
            "inbox", 
            "source:web"
          ], 
          "sender": {
            "name": "Adam Client", 
            "email": "100004967623158@facebook.com", 
            "user_id": "100004967623158"
          }, 
          "recipients": [
            {
              "name": "MB Aerospace Corp.", 
              "email": "507447822604742@facebook.com", 
              "user_id": "507447822604742"
            }, 
            {
              "name": "Adam Client", 
              "email": "100004967623158@facebook.com", 
              "user_id": "100004967623158"
            }
          ], 
          "object_sender": null, 
          "html_body": "Have a look on http://www.weather.com 1", 
          "attachments": [
          ], 
          "shares": [
            "38d79791ef0dac6f0b645a87f4d152d7"
          ], 
          "share_map": {
            "38d79791ef0dac6f0b645a87f4d152d7": {
              "media": [
              ], 
              "name": "National and Local Weather Forecast, Hurricane, Radar and Report", 
              "href": "http://www.weather.com/", 
              "caption": "www.weather.com", 
              "description": "The Weather Channel and weather.com provide a national and local weather forecast for cities, as well as weather radar, report and hurricane coverage.", 
              "properties": [
              ], 
              "fb_object_type": "", 
              "fb_object_id": "", 
              "icon": "https://fbstatic-a.akamaihd.net/rsrc.php/v2/yD/r/aS8ecmYRys0.gif", 
              "tagged_ids": [
              ]
            }
          }
        }
      ]
    }, 
    {
      "name": "users", 
      "fql_result_set": [
        {
          "uid": 100004967623158, 
          "first_name": "Adam", 
          "middle_name": "", 
          "last_name": "Client", 
          "name": "Adam Client", 
          "pic_small": "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-ash4/371585_100004967623158_2019810380_t.jpg", 
          "pic_big": "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-ash4/371585_100004967623158_2019810380_n.jpg", 
          "profile_update_time": 1360108999, 
          "timezone": null, 
          "religion": null, 
          "birthday": null, 
          "birthday_date": null, 
          "sex": "male", 
          "hometown_location": null, 
          "relationship_status": null, 
          "political": null, 
          "current_location": null, 
          "about_me": null, 
          "notes_count": null, 
          "wall_count": null, 
          "status": null, 
          "locale": "en_US", 
          "profile_url": "https://www.facebook.com/adam.client.5", 
          "verified": null, 
          "profile_blurb": null, 
          "username": "adam.client.5", 
          "is_blocked": false, 
          "email": null, 
          "friend_count": 1, 
          "languages": [
          ]
        }
      ]
    }
  ]
}

最后一个。我使用重新定义的 FacebookClient。源代码取自这里,stackoverflow.com。我不记得确切的原因,但类似于 DefaultFacebookClient 无法正确映射来自 Facebook 的结果(消息的附件)。

public class MyDefaultFacebokClient extends DefaultFacebookClient {


@Override public <T> T executeMultiquery (Map<String, String> queries, Class<T> objectType, Parameter... parameters)
{
verifyParameterPresence("objectType", objectType);
for (Parameter parameter : parameters)
if (QUERY_PARAM_NAME.equals(parameter.name))
throw new IllegalArgumentException("You cannot specify the '" + QUERY_PARAM_NAME
+ "' URL parameter yourself - " + "RestFB will populate this for you with "
+ "the queries you passed to this method.");

try {
List<JsonObject> jsonObjects = jsonMapper.toJavaList(makeRequest("fql", false, false, null,
parametersWithAdditionalParameter(Parameter.with("q", queriesToJson(queries)), parameters)), JsonObject.class);

JsonObject normalizedJson = new JsonObject();

for (int i = 0; i < jsonObjects.size(); i++)
{
JsonObject jsonObject = jsonObjects.get(i);

// For empty result sets, Facebook will return an empty object instead of
// an empty list. Hack around that here.
JsonArray resultsArray =
jsonObject.get("fql_result_set") instanceof JsonArray ? jsonObject.getJsonArray("fql_result_set")
: new JsonArray();

normalizedJson.put(jsonObject.getString("name"), resultsArray);
}

return objectType.equals(JsonObject.class) ? (T) normalizedJson : jsonMapper.toJavaObject(normalizedJson.toString(), objectType);

} catch (JsonException e) {
throw new FacebookJsonMappingException("Unable to process fql.multiquery JSON response", e);
}
}
}

任何想法将不胜感激。

4

1 回答 1

0

我是 RestFB 的作者。也许从 Github 中提取最新的,运行“ant dist”来创建 1.6.12 JAR,并尝试调用新的 FacebookClient.executeFqlMultiquery 方法而不是 FacebookClient.executeMultiquery()。

新的 Graph API FQL 端点与旧端点略有不同,这个新的 executeFqlMultiquery() 方法有望解决您看到的问题。如果没有,或者您在正确映射结果类型时遇到问题,请告诉我。

下面是如何使用新方法的快速示例,从https://groups.google.com/forum/?fromgroups=#!topic/restfb/yjCxSQuiieE复制:

static void test() throws Exception {
  FacebookClient facebookClient = new DefaultFacebookClient("xxx");

  final String threadsFql =
      "SELECT action_id, archived, can_reply, folder, former_participants, has_attachments, "
          + "is_subscribed, last_visible_add_action_id, name, num_messages, num_unread, object_participants, "
          + "participants, senders, single_recipient, snippet, snippet_sender, snippet_message_has_attachment, "
          + "subject, tags, thread_id, thread_participants, timestamp, unread "
          + "FROM unified_thread WHERE folder='inbox' AND has_attachments='1'";

  final String messagesFql =
      "SELECT message_id, thread_id, subject, body, unread, action_id, timestamp, tags, sender, recipients, "
          + "object_sender, html_body, attachments, attachment_map, shares, share_map "
          + "FROM unified_message WHERE thread_id IN (SELECT thread_id FROM #threads) LIMIT 2";

  ComplexMappingResults results = facebookClient.executeFqlMultiquery(new HashMap<String, String>() {
    {
      put("threads", threadsFql);
      put("messages", messagesFql);
    }
  }, ComplexMappingResults.class);

  out.println(results);
}

public static class ComplexMappingResults {
  @Facebook
  private List<Thread> threads;

  @Facebook
  private List<Message> messages;

  @Override
  public String toString() {
    return ReflectionUtils.toString(this);
  }

  public List<Thread> getThreads() {
    return threads;
  }

  public List<Message> getMessages() {
    return messages;
  }
}
于 2013-02-06T21:57:58.563 回答