2013-09-30 514 views
2

我試圖反序列化與RateString.Text的Twitter RateLimit Json。我創建了一個適當的DTO對象(查看帖子的底部),讓JSON被拉下來。我利用System.Runtime.Serialization將字段重命名爲更友好的名稱(我在Twitter的許多其他DTO對象中使用了此名稱)。反序列化對象時,RateLimitContext正確反序列化,但是在資源反序列化下的所有項目都爲空。我懷疑這個特定對象的DataMemberNames有問題,因爲它們包含幾個「特殊」字符。這是ServiceStack.Text中的一個錯誤還是我在DTO中丟失了一些東西?ServiceStack.Text和Twitter JSON

{ 
"rate_limit_context": { 
    "access_token": "ajksldjalsda-akjflkasjfltpowfaalksjdfAPQPIJFaflkjaq" 
}, 
"resources": { 
    "lists": { 
     "/lists/subscribers": { 
      "limit": 180, 
      "remaining": 180, 
      "reset": 1380314146 
     }, 
     "/lists/list": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/lists/memberships": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/lists/ownerships": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/lists/subscriptions": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/lists/members": { 
      "limit": 180, 
      "remaining": 180, 
      "reset": 1380314146 
     }, 
     "/lists/subscribers/show": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/lists/statuses": { 
      "limit": 180, 
      "remaining": 180, 
      "reset": 1380314146 
     }, 
     "/lists/members/show": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/lists/show": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     } 
    }, 
    "application": { 
     "/application/rate_limit_status": { 
      "limit": 180, 
      "remaining": 178, 
      "reset": 1380314022 
     } 
    }, 
    "friendships": { 
     "/friendships/incoming": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/friendships/lookup": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/friendships/outgoing": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/friendships/no_retweets/ids": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/friendships/show": { 
      "limit": 180, 
      "remaining": 180, 
      "reset": 1380314146 
     } 
    }, 
    "blocks": { 
     "/blocks/ids": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/blocks/list": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     } 
    }, 
    "geo": { 
     "/geo/similar_places": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/geo/search": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/geo/reverse_geocode": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/geo/id/:place_id": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     } 
    }, 
    "users": { 
     "https://stackoverflow.com/users/profile_banner": { 
      "limit": 180, 
      "remaining": 180, 
      "reset": 1380314146 
     }, 
     "https://stackoverflow.com/users/suggestions/:slug/members": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "https://stackoverflow.com/users/show/:id": { 
      "limit": 180, 
      "remaining": 180, 
      "reset": 1380314146 
     }, 
     "https://stackoverflow.com/users/suggestions": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "https://stackoverflow.com/users/lookup": { 
      "limit": 180, 
      "remaining": 180, 
      "reset": 1380314146 
     }, 
     "https://stackoverflow.com/users/search": { 
      "limit": 180, 
      "remaining": 180, 
      "reset": 1380314146 
     }, 
     "https://stackoverflow.com/users/contributors": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "https://stackoverflow.com/users/contributees": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "https://stackoverflow.com/users/suggestions/:slug": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     } 
    }, 
    "prompts": { 
     "/prompts/record_event": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/prompts/suggest": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     } 
    }, 
    "followers": { 
     "/followers/list": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/followers/ids": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     } 
    }, 
    "statuses": { 
     "/statuses/mentions_timeline": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/statuses/show/:id": { 
      "limit": 180, 
      "remaining": 180, 
      "reset": 1380314146 
     }, 
     "/statuses/oembed": { 
      "limit": 180, 
      "remaining": 180, 
      "reset": 1380314146 
     }, 
     "/statuses/retweeters/ids": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/statuses/home_timeline": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/statuses/user_timeline": { 
      "limit": 180, 
      "remaining": 180, 
      "reset": 1380314146 
     }, 
     "/statuses/retweets/:id": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/statuses/retweets_of_me": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     } 
    }, 
    "help": { 
     "/help/privacy": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/help/tos": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/help/configuration": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/help/languages": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     } 
    }, 
    "friends": { 
     "/friends/ids": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/friends/list": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     } 
    }, 
    "direct_messages": { 
     "/direct_messages/show": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/direct_messages/sent_and_received": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/direct_messages/sent": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/direct_messages": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     } 
    }, 
    "account": { 
     "/account/verify_credentials": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/account/settings": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     } 
    }, 
    "favorites": { 
     "/favorites/list": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     } 
    }, 
    "saved_searches": { 
     "/saved_searches/destroy/:id": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/saved_searches/list": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/saved_searches/show/:id": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     } 
    }, 
    "search": { 
     "/search/tweets": { 
      "limit": 180, 
      "remaining": 180, 
      "reset": 1380314146 
     } 
    }, 
    "trends": { 
     "/trends/available": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/trends/place": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     }, 
     "/trends/closest": { 
      "limit": 15, 
      "remaining": 15, 
      "reset": 1380314146 
     } 
    } 
} 

}

回答

0

[DataMember]名稱的只針對指定字段名別名,即他們沒有嵌套,並能」:

[DataContract] 
public class RateLimitResult 
{ 
    [DataMember(Name = "rate_limit_context")] 
    public RateLimitContextEntry RateLimitContext { get; set; } 

    [DataContract] 
    public class RateLimitContextEntry 
    { 
     [DataMember(Name = "access_token")] 
     public string AccessToken { get; set; } 
    } 

    [DataMember(Name = "resources")] 
    public ResourcesEntry Resources { get; set; } 

    [DataContract] 
    public class RateLimitEntry 
    { 
     [DataMember(Name = "remaining")] 
     public int Remaining { get; set; } 

     [DataMember(Name = "reset")] 
     public long Reset { get; set; } 

     [DataMember(Name = "limit")] 
     public int Limit { get; set; } 
    } 

    [DataContract] 
    public class HelpEntry 
    { 
     [DataMember(Name = "/help/privacy")] 
     public RateLimitEntry Privacy { get; set; } 

     [DataMember(Name = "/help/configuration")] 
     public RateLimitEntry Configuration { get; set; } 

     [DataMember(Name = "/help/tos")] 
     public RateLimitEntry Tos { get; set; } 

     [DataMember(Name = "/help/languages")] 
     public RateLimitEntry Languages { get; set; } 
    } 

    [DataContract] 
    public class StatusesEntry 
    { 
     [DataMember(Name = "/statuses/oembed")] 
     public RateLimitEntry Oembed { get; set; } 

     [DataMember(Name = "/statuses/user_timeline")] 
     public RateLimitEntry UserTimeline { get; set; } 

     [DataMember(Name = "/statuses/mentions_timeline")] 
     public RateLimitEntry MentionsTimeline { get; set; } 

     [DataMember(Name = "/statuses/home_timeline")] 
     public RateLimitEntry HomeTimeline { get; set; } 

     [DataMember(Name = "/statuses/show/:id")] 
     public RateLimitEntry ShowId { get; set; } 

     [DataMember(Name = "/statuses/retweets/:id")] 
     public RateLimitEntry RetweetsId { get; set; } 

     [DataMember(Name = "/statuses/retweets_of_me")] 
     public RateLimitEntry RetweetsOfMe { get; set; } 
    } 

    [DataContract] 
    public class UsersEntry 
    { 
     [DataMember(Name = "https://stackoverflow.com/users/search")] 
     public RateLimitEntry Search { get; set; } 

     [DataMember(Name = "https://stackoverflow.com/users/suggestions")] 
     public RateLimitEntry Suggestions { get; set; } 

     [DataMember(Name = "https://stackoverflow.com/users/contributors")] 
     public RateLimitEntry Contributors { get; set; } 

     [DataMember(Name = "https://stackoverflow.com/users/suggestions/:slug/members")] 
     public RateLimitEntry SuggestionsSlugMembers { get; set; } 

     [DataMember(Name = "https://stackoverflow.com/users/suggestions/:slug")] 
     public RateLimitEntry SuggestionsSlug { get; set; } 

     [DataMember(Name = "https://stackoverflow.com/users/contributees")] 
     public RateLimitEntry Contributees { get; set; } 

     [DataMember(Name = "https://stackoverflow.com/users/lookup")] 
     public RateLimitEntry Lookup { get; set; } 

     [DataMember(Name = "https://stackoverflow.com/users/profile_banner")] 
     public RateLimitEntry ProfileBanner { get; set; } 
    } 

    [DataContract] 
    public class SearchEntry 
    { 
     [DataMember(Name = "/search/tweets")] 
     public RateLimitEntry Tweets { get; set; } 
    } 

    [DataContract] 
    public class TrendsEntry 
    { 
     [DataMember(Name = "/trends/available")] 
     public RateLimitEntry Available { get; set; } 

     [DataMember(Name = "/trends/place")] 
     public RateLimitEntry Place { get; set; } 

     [DataMember(Name = "/trends/closest")] 
     public RateLimitEntry Closest { get; set; } 
    } 

    [DataContract] 
    public class SavedSearchesEntry 
    { 
     [DataMember(Name = "/saved_searches/destroy/:id")] 
     public RateLimitEntry DestroyId { get; set; } 

     [DataMember(Name = "/saved_searches/list")] 
     public RateLimitEntry List { get; set; } 

     [DataMember(Name = "/saved_searches/show/:id")] 
     public RateLimitEntry ShowId { get; set; } 
    } 

    [DataContract] 
    public class FavoritesEntry 
    { 
     [DataMember(Name = "/favorites/list")] 
     public RateLimitEntry List { get; set; } 
    } 

    [DataContract] 
    public class AccountEntry 
    { 
     [DataMember(Name = "/account/verify_credentials")] 
     public RateLimitEntry VerifyCredentials { get; set; } 

     [DataMember(Name = "/account/settings")] 
     public RateLimitEntry Settings { get; set; } 
    } 

    [DataContract] 
    public class DirectMessagesEntry 
    { 
     [DataMember(Name = "/direct_messages/show")] 
     public RateLimitEntry Show { get; set; } 

     [DataMember(Name = "/direct_messages/sent_and_received")] 
     public RateLimitEntry SentAndReceived { get; set; } 

     [DataMember(Name = "/direct_messages/sent")] 
     public RateLimitEntry Sent { get; set; } 

     [DataMember(Name = "/direct_messages")] 
     public RateLimitEntry Messages { get; set; } 
    } 

    [DataContract] 
    public class FriendsEntry 
    { 
     [DataMember(Name = "/friends/ids")] 
     public RateLimitEntry Ids { get; set; } 

     [DataMember(Name = "/friends/list")] 
     public RateLimitEntry List { get; set; } 
    } 

    [DataContract] 
    public class FollowersEntry 
    { 
     [DataMember(Name = "/followers/list")] 
     public RateLimitEntry List { get; set; } 

     [DataMember(Name = "/followers/ids")] 
     public RateLimitEntry Ids { get; set; } 
    } 

    [DataContract] 
    public class PromptsEntry 
    { 
     [DataMember(Name = "/prompts/record_event")] 
     public RateLimitEntry RecordEvent { get; set; } 

     [DataMember(Name = "/prompts/suggest")] 
     public RateLimitEntry Suggest { get; set; } 
    } 

    [DataContract] 
    public class GeoEntry 
    { 
     [DataMember(Name = "/geo/similar_places")] 
     public RateLimitEntry SimilarPlaces { get; set; } 

     [DataMember(Name = "/geo/search")] 
     public RateLimitEntry Search { get; set; } 

     [DataMember(Name = "/geo/reverse_geocode")] 
     public RateLimitEntry ReverseGeocode { get; set; } 

     [DataMember(Name = "/geo/id/:place_id")] 
     public RateLimitEntry PlaceId { get; set; } 
    } 

    [DataContract] 
    public class BlocksEntry 
    { 
     [DataMember(Name = "/blocks/ids")] 
     public RateLimitEntry Ids { get; set; } 

     [DataMember(Name = "/blocks/list")] 
     public RateLimitEntry List { get; set; } 
    } 

    [DataContract] 
    public class FriendshipsEntry 
    { 
     [DataMember(Name = "/friendships/incoming")] 
     public RateLimitEntry Incoming { get; set; } 

     [DataMember(Name = "/friendships/lookup")] 
     public RateLimitEntry Lookup { get; set; } 

     [DataMember(Name = "/friendships/outgoing")] 
     public RateLimitEntry Outgoing { get; set; } 

     [DataMember(Name = "/friendships/no_retweets/ids")] 
     public RateLimitEntry NoRetweetsIds { get; set; } 

     [DataMember(Name = "/friendships/show")] 
     public RateLimitEntry Show { get; set; } 
    } 

    [DataContract] 
    public class ApplicationEntry 
    { 
     [DataMember(Name = "/application/rate_limit_status")] 
     public RateLimitEntry RateLimitStatus { get; set; } 
    } 

    [DataContract] 
    public class ListsEntry 
    { 
     [DataMember(Name = "/lists/subscribers")] 
     public RateLimitEntry Subscribers { get; set; } 

     [DataMember(Name = "/lists/list")] 
     public RateLimitEntry List { get; set; } 

     [DataMember(Name = "/lists/memberships")] 
     public RateLimitEntry Memberships { get; set; } 

     [DataMember(Name = "/lists/ownerships")] 
     public RateLimitEntry Ownerships { get; set; } 

     [DataMember(Name = "/lists/subscriptions")] 
     public RateLimitEntry Subscriptions { get; set; } 

     [DataMember(Name = "/lists/members")] 
     public RateLimitEntry Members { get; set; } 

     [DataMember(Name = "/lists/subscribers/show")] 
     public RateLimitEntry ShowSubscribers { get; set; } 

     [DataMember(Name = "/lists/statuses")] 
     public RateLimitEntry Statuses { get; set; } 

     [DataMember(Name = "/lists/members/show")] 
     public RateLimitEntry ShowMembers { get; set; } 

     [DataMember(Name = "/lists/show")] 
     public RateLimitEntry Show { get; set; } 
    } 

    [DataContract] 
    public class ResourcesEntry 
    { 
     [DataMember(Name = "lists")] 
     public ListsEntry Lists { get; set; } 

     [DataMember(Name = "application")] 
     public ApplicationEntry Application { get; set; } 

     [DataMember(Name = "friendships")] 
     public FriendshipsEntry Friendships { get; set; } 

     [DataMember(Name = "blocks")] 
     public BlocksEntry Blocks { get; set; } 

     [DataMember(Name = "geo")] 
     public GeoEntry Geo { get; set; } 

     [DataMember(Name = "users")] 
     public UsersEntry Users { get; set; } 

     [DataMember(Name = "prompts")] 
     public PromptsEntry Prompts { get; set; } 

     [DataMember(Name = "followers")] 
     public FollowersEntry Followers { get; set; } 

     [DataMember(Name = "statuses")] 
     public StatusesEntry Statuses { get; set; } 

     [DataMember(Name = "help")] 
     public HelpEntry Help { get; set; } 

     [DataMember(Name = "friends")] 
     public FriendsEntry Friends { get; set; } 

     [DataMember(Name = "direct_messages")] 
     public DirectMessagesEntry DirectMessages { get; set; } 

     [DataMember(Name = "account")] 
     public AccountEntry Account { get; set; } 

     [DataMember(Name = "favorites")] 
     public FavoritesEntry Favorites { get; set; } 

     [DataMember(Name = "saved_searches")] 
     public SavedSearchesEntry SavedSearches { get; set; } 

     [DataMember(Name = "search")] 
     public SearchEntry Search { get; set; } 

     [DataMember(Name = "trends")] 
     public TrendsEntry Trends { get; set; } 
    } 
} 

這裏是樣品的Json API返回t包含非字母數字字符,就像你在這裏完成的那樣。

下面是一個Twitter DTOs for use in ServiceStack串行器的示例。

+0

我應該提到,JSON.Net與這些字段名稱沒有問題。當我試圖交換反序列化器時,我只遇到了這個問題。 –

+0

我更新了由API返回的示例Json的帖子。您對處理這些字段名稱有任何建議嗎? –

+0

使用一個匹配JSON的屬性,比如'Dictionary Lists'或[動態解析它](https://github.com/ServiceStack/ServiceStack.Text#supports-dynamic-json) – mythz