精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

HandyJSON:Swift語言JSON轉Model工具庫

移動開發 移動應用
JSON是移動端開發常用的應用層數據交換協議。最常見的場景便是,客戶端向服務端發起網絡請求,服務端返回JSON文本,然后客戶端解析這個JSON文本,再把對應數據展現到頁面上。

背景

JSON是移動端開發常用的應用層數據交換協議。最常見的場景便是,客戶端向服務端發起網絡請求,服務端返回JSON文本,然后客戶端解析這個JSON文本,再把對應數據展現到頁面上。

但在編程的時候,處理JSON是一件麻煩事。在不引入任何輪子的情況下,我們通常需要先把JSON轉為Dictionary,然后還要記住每個數據對應的Key,用這個Key在Dictionary中取出對應的Value來使用。這個過程我們會犯各種錯誤:

  • Key拼寫錯了;
  • 路徑寫錯了;
  • 類型搞錯了;
  • 沒拿到值懵逼了;
  • 某一天和服務端約定的某個字段變更了,沒能更新所有用到它的地方;
  • ...

為了解決這些問題,很多處理JSON的開源庫應運而生。在Swift中,這些開源庫主要朝著兩個方向努力:

  • 保持JSON語義,直接解析JSON,但通過封裝使調用方式更優雅、更安全;
  • 預定義Model類,將JSON反序列化為類實例,再使用這些實例;

對于1,使用最廣、評價***的庫非 SwiftyJSON 莫屬,它很能代表這個方向的核心。它本質上仍然是根據JSON結構去取值,使用起來順手、清晰。但也正因如此,這種做法沒能妥善解決上述的幾個問題,因為Key、路徑、類型仍然需要開發者去指定;

對于2,我個人覺得這是更合理的方式。由于Model類的存在,JSON的解析和使用都受到了定義的約束,只要客戶端和服務端約定好了這個Model類,客戶端定義后,在業務中使用數據時就可以享受到語法檢查、屬性預覽、屬性補全等好處,而且一旦數據定義變更,編譯器會強制所有用到的地方都改過來才能編譯通過,非常安全。這個方向上,開源庫們做的工作,主要就是把JSON文本反序列化到Model類上了。這一類JSON庫有 ObjectMapper、JSONNeverDie、HandyJSON 等。而 HandyJSON 是其中使用最舒服的一個庫,本文將介紹用 HandyJSON 來進行Model和JSON間的互相轉換。

項目地址:https://github.com/alibaba/handyjson

為什么用HandyJSON

在Swift中把JSON反序列化到Model類,在HandyJSON出現以前,主要使用兩種方式:

  • 讓Model類繼承自NSObject,然后class_copyPropertyList()方法獲取屬性名作為Key,從JSON中取得Value,再通過Objective-C runtime支持的KVC機制為類屬性賦值;如JSONNeverDie;
  • 支持純Swift類,但要求開發者實現Mapping函數,使用重載的運算符進行賦值,如ObjectMapper;

這兩者都有顯而易見的缺點。前者要求Model繼承自NSObject,非常不優雅,且直接否定了用struct來定義Model的方式;后者的Mapping函數要求開發者自定義,在其中指明每個屬性對應的JSON字段名,代碼侵入大,且仍然容易發生拼寫錯誤、維護困難等問題。

而HandyJSON另辟蹊徑,采用Swift反射+內存賦值的方式來構造Model實例,規避了上述兩個方案遇到的問題。

把JSON轉換為Model

簡單類型

某個Model類想支持通過HandyJSON來反序列化,只需要在定義時,實現HandyJSON協議,這個協議只要求實現一個空的init()函數。

比如我們和服務端約定了一個Animal數據,里面有name/id/num字段,那么我們這樣定義Animal類:

  1. class Animal: HandyJSON { 
  2.     var name: String? 
  3.     var id: String? 
  4.     var num: Int
  5.  
  6.     required init() {} 

然后假設我們從服務端拿到這樣一個JSON文本: 

  1. let jsonString = "{\"name\":\"cat\",\"id\":\"12345\",\"num\":180}" 

引入HandyJSON以后,我們就可以這樣來做反序列化了:

  1. if let animal = JSONDeserializer<Animal>.deserializeFrom(json: jsonString) { 
  2.     print(animal.name
  3.     print(animal.id) 
  4.     print(animal.num) 

簡單吧~

支持Struct

如果Model的定義是struct,由于Swift中struct提供了默認構造函數,所以就不需要再實現空的init()函數了。但需要注意,如果你為strcut指定了別的構造函數,那么就需要保留一個空的實現。

  1. struct Animal: HandyJSON { 
  2.     var name: String? 
  3.     var id: String? 
  4.     var num: Int
  5.  
  6. let jsonString = "{\"name\":\"cat\",\"id\":\"12345\",\"num\":180}" 
  7.  
  8. if let animal = JSONDeserializer<Animal>.deserializeFrom(json: jsonString) { 
  9.     print(animal) 

比較復雜的類型

HandyJSON支持在類定義里使用各種形式的基本屬性,包括可選(?),隱式解包可選(!),數組(Array),字典(Dictionary),Objective-C基本類型(NSString、NSNumber),各種類型的嵌套([Int]?、[String]?、[Int]!、...)等等。比如下面這個看起來比較復雜的類型:

  1. class Cat: HandyJSON { 
  2.     var id: Int64! 
  3.     var name: String! 
  4.     var friend: [String]? 
  5.     var weight: Double
  6.     var alive: Bool = true 
  7.     var color: NSString? 
  8.  
  9.     required init() {} 

一樣輕松轉換:

  1. let jsonString = "{\"id\":1234567,\"name\":\"Kitty\",\"friend\":[\"Tom\",\"Jack\",\"Lily\",\"Black\"],\"weight\":15.34,\"alive\":false,\"color\":\"white\"}" 
  2.  
  3. if let cat = JSONDeserializer<Cat>.deserializeFrom(json: jsonString) { 
  4.     print(cat.xxx) 

嵌套的Model類

如果Model類中的某個屬性是另一個自定義的Model類,那么只要那個Model類也實現了HandyJSON協議,就一樣可以轉換:

  1. class Component: HandyJSON { 
  2.     var aInt: Int
  3.     var aString: String? 
  4.  
  5.     required init() {} 
  6.  
  7. class Composition: HandyJSON { 
  8.     var aInt: Int
  9.     var comp1: Component? 
  10.     var comp2: Component? 
  11.  
  12.     required init() {} 
  13.  
  14. let jsonString = "{\"num\":12345,\"comp1\":{\"aInt\":1,\"aString\":\"aaaaa\"},\"comp2\":{\"aInt\":2,\"aString\":\"bbbbb\"}}" 
  15.  
  16. if let composition = JSONDeserializer<Composition>.deserializeFrom(json: jsonString) { 
  17.     print(composition) 

指定反序列化JSON中某個節點

有時候服務端返回給我們的JSON文本包含了大量的狀態信息,和Model無關,比如statusCode,debugMessage等,或者有用的數據是在某個節點以下,那么我們可以指定反序列化哪個節點:

  1. class Cat: HandyJSON { 
  2.     var id: Int64! 
  3.     var name: String! 
  4.  
  5.     required init() {} 
  6.  
  7.  
  8. // 服務端返回了這個JSON,我們想解析的只有data里的cat 
  9. let jsonString = "{\"code\":200,\"msg\":\"success\",\"data\":{\"cat\":{\"id\":12345,\"name\":\"Kitty\"}}}" 
  10.  
  11. // 那么,我們指定解析 "data.cat",通過點來表達路徑 
  12. if let cat = JSONDeserializer<Cat>.deserializeFrom(json: jsonString, designatedPath: "data.cat") { 
  13.     print(cat.name

有繼承關系的Model類

如果某個Model類繼承自另一個Model類,只需要這個父Model類實現HandyJSON協議就可以:

  1. class Animal: HandyJSON { 
  2.     var id: Int
  3.     var color: String? 
  4.  
  5.     required init() {} 
  6.  
  7.  
  8. class Cat: Animal { 
  9.     var name: String? 
  10.  
  11.     required init() {} 
  12.  
  13. let jsonString = "{\"id\":12345,\"color\":\"black\",\"name\":\"cat\"}" 
  14.  
  15. if let cat = JSONDeserializer<Cat>.deserializeFrom(json: jsonString) { 
  16.     print(cat) 

自定義解析方式

HandyJSON還提供了一個擴展能力,就是允許自行定義Model類某個字段的解析Key、解析方式。我們經常會有這樣的需求:

  • 某個Model中,我們不想使用和服務端約定的key作為屬性名,想自己定一個;
  • 有些類型如enum、tuple是無法直接從JSON中解析出來的,但我們在Model類中有這樣的屬性;

HandyJSON協議提供了一個可選的mapping()函數,我們可以在其中指定某個字段用什么Key、或者用什么方法從JSON中解析出它的值。如我們有一個Model類和一個服務端返回的JSON串:

  1. class Cat: HandyJSON { 
  2.     var id: Int64! 
  3.     var name: String! 
  4.     var parent: (String, String)? 
  5.  
  6.     required init() {} 
  7.  
  8. let jsonString = "{\"cat_id\":12345,\"name\":\"Kitty\",\"parent\":\"Tom/Lily\"}" 

可以看到,Cat類的id屬性和JSON文本中的Key是對應不上的;而對于parent這個屬性來說,它是一個元組,做不到從JSON中的"Tom/Lily"解析出來。所以我們要定義一個Mapping函數來做這兩個支持:

  1. class Cat: HandyJSON { 
  2.     var id: Int64! 
  3.     var name: String! 
  4.     var parent: (String, String)? 
  5.  
  6.     required init() {} 
  7.  
  8.     func mapping(mapper: HelpingMapper) { 
  9.         // 指定 id 字段用 "cat_id" 去解析 
  10.         mapper.specify(property: &id, name"cat_id"
  11.  
  12.         // 指定 parent 字段用這個方法去解析 
  13.         mapper.specify(property: &parent) { (rawString) -> (String, String) in 
  14.             let parentNames = rawString.characters.split{$0 == "/"}.map(String.init) 
  15.             return (parentNames[0], parentNames[1]) 
  16.         } 
  17.     } 

就這樣,HandyJSON***地幫我們進行了JSON到Model類的轉換。如此方便,這也是將其命名為Handy的由來。

把Model轉換為JSON文本

HandyJSON還提供了把Model類序列化為JSON文本的能力,簡直無情。

基本類型

如果只需要進行序列化,那么在定義Model類時,不需要做任何特殊的改動。任何一個類的實例,直接調用HandyJSON的序列化方法去序列化,就能得到JSON字符串了。

  1. class Animal { 
  2.     var name: String? 
  3.     var height: Int
  4.  
  5.     init(name: String, height: Int) { 
  6.         self.name = name 
  7.         self.height = height 
  8.     } 
  9.  
  10. let cat = Animal(name"cat", height: 30) 
  11.  
  12. // 序列化為簡單JSON文本 
  13. if let jsonStr = JSONSerializer.serialize(model: cat).toJSON() { 
  14.     print("simple json string: ", jsonStr) 
  15.  
  16. // 序列化為格式化的JSON文本 
  17. if let prettifyJSON = JSONSerializer.serialize(model: cat).toPrettifyJSON() { 
  18.     print("prettify json string: ", prettifyJSON) 
  19.  
  20. // 序列化為簡單字典 
  21. if let dict = JSONSerializer.serialize(model: cat).toSimpleDictionary() { 
  22.     print("dictionary: ", dict) 

復雜類型

即使Model類中有別的Model類啥的,都一樣支持。

  1. enum Gender { 
  2.     case Male 
  3.     case Female 
  4.  
  5. struct Subject { 
  6.     var id: Int64? 
  7.     var name: String? 
  8.  
  9.     init(id: Int64, name: String) { 
  10.         self.id = id 
  11.         self.name = name 
  12.     } 
  13.  
  14. class Student { 
  15.     var name: String? 
  16.     var gender: Gender? 
  17.     var subjects: [Subject]? 
  18.  
  19. let student = Student() 
  20. student.name = "Jack" 
  21. student.gender = .Female 
  22. student.subjects = [Subject(id: 1, name"math"), Subject(id: 2, name"English"), Subject(id: 3, name"Philosophy")] 
  23.  
  24. if let jsonStr = JSONSerializer.serialize(model: student).toJSON() { 
  25.     print("simple json string: ", jsonStr) 
  26. if let prettifyJSON = JSONSerializer.serialize(model: student).toPrettifyJSON() { 
  27.     print("prettify json string: ", prettifyJSON) 
  28. if let dict = JSONSerializer.serialize(model: student).toSimpleDictionary() { 
  29.     print("dictionary: ", dict) 

總結

有了HandyJSON的支持,現在我們可以開心地在Swift中使用JSON了。這個庫支持了Swift 2.2+, Swift 3.0+。如果大家有什么需求或者建議,可以去 https://github.com/alibaba/handyjson 提issue.

為何開發HandyJSON

我所在iOS團隊是從去年11月份切Swift的。我們服務端和客戶端數據交互格式一直用的是JSON,而當時Swift中處理JSON名氣比較大的庫貌似只有SwiftyJSON,工程切到Swift后,我們也用了這個庫。用上之后,需求是滿足了,但是對一些復雜的Model,代碼寫得看起來非常糟糕,因為每次取值都需要 json["akey"]["bkey"]["ckey"].value 形式,寫的時候對著文檔沒覺得啥問題,但過后在脫離文檔的情況下,通篇都是字符串表達的key,很難從代碼中感覺出Model結構。所以我們都會把一段sample數據寫在注釋里。但仍然比較凌亂,另外key寫錯了debug起來也費勁,一個大小寫問題有時候debug半天。

于是我們進化了一下,先寫好Model,然后Model類中寫convert函數,也用上了KVC遍歷key賦值。寫起來舒服多了,但還是麻煩,而且要求每一個類都繼承自NSObject。不久后,我們認識了ObjectMapper庫,二話不說,就換了上去。世界頓時干凈多了。

但還是感覺差了一點,因為ObjectMapper需要自己指明映射關系。通常JSON中key和Model中字段名都是一致的,每次都要額外寫一坨東西,總覺得多余,字段有改動的時候也費勁。新來剛接觸Swift的同事,也表示不太舒服,因為他們之前使用的JSON反序列化庫,無論Java中還是Objective-C中,都是自然使用Model字段名去取值的。

所以就想著研究一下,Swift中能不能做到這種效果。

HandyJSON的設計思路

Swift中存在的限制

無論是Java或者Objective-C中的JSON反序列化庫,通常都是,在運行時獲取Model的字段名集合,遍歷該集合,拿Key去JSON中取值并完成賦值。這些步驟,Java依賴反射機制可以實現,Objective-C通過class_copyPropertyList方法加上KVC機制,也能輕松實現。而Swift會卡在***一步:無法賦值。

Swift的反射是只讀的,就是說,我們能在運行時獲取一個Model實例的所有字段、字段值,但卻無法給它賦值。事實上,我們拿到的value是原值的一個只讀拷貝,即使獲取到這個拷貝的地址寫入新值,也是無效的。

  1. class Animal { 
  2.     var name: String? 
  3.  
  4. Mirror(reflecting: Animal()).children.forEach { (child) in 
  5.     print(child.label ?? "", child.value) // working correctly 
  6.     child.value = "cat" // error,不能直接賦值 

而且迄今,蘋果官網文檔上對實現反射機制的Mirror類仍然是這么描述: Mirrors are used by playgrounds and the debugger,態度非常含糊,似乎不太鼓勵,但生產中很多類庫都用上了。只能說,蘋果不會輕易撤下這個能力,但期待它對這個能力做出改進(比如支持運行時賦值),是希望渺茫的。

如何繞過限制

最簡單的方式,就是在Swift中定義Model時繼承NSObject,讓這個Model的實例存在于objc運行時中,上述的class_copyPropertyList方法和KVC就能用上了。目前看見的Swift中不需要指明映射關系的JSON庫,都是這種方式。

然后就是以ObjectMapper為代表的庫,通過運算符重載,在指定映射關系時完成賦值。走這一類實現的庫也非常多了。

但我想做到的是,既支持運行在Swift運行時的純Swift類,又不需要顯示指定每一個字段的映射關系。那么,不能走反射賦值,那就直接寫入內存吧。

具體實現

Swift中,一個類實例的內存布局是有規律的:

  • 32位機器上,類前面有4+8個字節存儲meta信息,64位機器上,有8+8個字節;
  • 內存中,字段從前往后有序排列;
  • 如果該類繼承自某一個類,那么父類的字段在前;
  • Optional會增加一個字節來存儲.None/.Some信息;
  • 每個字段需要考慮內存對齊;

這方面基本沒有官方的資料參考,上述規律一些是從網上其他大神的總結中收集,一些從Clang的一些說明文檔中挖掘,還有一些是自己在playground里試出來的。開始心里沒什么底,但把HandyJSON實現出來使用這么久了,還沒出過狀況,可以認為是靠譜的。

有法子計算內存布局,剩下的事情就比較簡單了。對一個實例:

  • 獲取它的起始指針,移動到有效起點;
  • 通過Mirror獲取每一個字段的字段名和字段類型;
  • 根據字段名在JSON中取值,轉換為和字段一樣的類型,通過指針寫入;
  • 根據本字段類型的占位大小和下一個字段類型計算下一個字段的對齊起點;
  • 移動指針,繼續處理;

獲取類實例的起始指針

Swift中,獲取struct實例起始指針和獲取class實例起始指針的方法是不一樣的,和語言版本也相關。在Swift3中:

  1. // 獲取struct實例起始指針 
  2. mutating func headPointerOfStruct() -> UnsafeMutablePointer<Byte> { 
  3.  
  4.     return withUnsafeMutablePointer(to: &self) { 
  5.         return UnsafeMutableRawPointer($0).bindMemory(to: Byte.self, capacity: MemoryLayout<Self>.stride) 
  6.     } 
  7.  
  8. // 獲取class實例起始指針 
  9. mutating func headPointerOfClass() -> UnsafeMutablePointer<Byte> { 
  10.  
  11.     let opaquePointer = Unmanaged.passUnretained(self as AnyObject).toOpaque() 
  12.     let mutableTypedPointer = opaquePointer.bindMemory(to: Byte.self, capacity: MemoryLayout<Self>.stride) 
  13.     return UnsafeMutablePointer<Byte>(mutableTypedPointer) 

通過Mirror獲取字段名、類型

  1. Mirror(reflecting: Animal()).children.forEach { (child) in 
  2.     print(child.label ?? "") // 獲取字段名 
  3.     print(type(of: child.value)) // 獲取字段類型 

計算Model的每個屬性字段占位大小

Swift3暴露了兩個接口用于計算類型占位大小:MemoryLayout.size(ofValue: T)和MemoryLayout.size。這兩者都沒辦法直接用,因為:

  • 對于每個屬性,我們目前只持有它的起始指針,而不是它的實例,***個接口用不上;
  • 對于每個屬性,我們是在運行時中獲取到它的類型,已經沒辦法再實例化出泛型類型MemoryLayout<T>來計算size。所以,我引入了HandyJSON類,在擴展中實現函數:
  1. protocol HandyJSON { 
  2.  
  3. extension HandyJSON { 
  4.     static func size() -> Int { 
  5.         return MemoryLayout<Self>.size 
  6.     } 

于是,對于每一個實現HandyJSON協議的Model類T,直接調用 T.size() 就能獲取到T的size了。

內存對齊的影響

類實例的屬性并不是直接按照各自占位大小依次往下排列的,不然事情就簡單了。和C/C++一樣,Swift中實例內存布局也考慮了內存對齊。翻閱了Swift的docs和LLVM的一些資料,MemoryLayout提供了一個接口:MemoryLayout.alignment,對齊的規則為,每個字段的起始地址必須為alignment值的整數倍。細節的出處我已經忘記。當時進行了一些復雜類型的測試后,認定它符合事實。所以HandyJSON中計算下一個字段起始地址的函數為:

  1. // Returns the offset to the next integer that is greater than 
  2. // or equal to Value and is a multiple of Align. Align must be 
  3. // non-zero. 
  4. static func offsetToAlignment(value: Int, align: Int) -> Int { 
  5.     let m = value % align 
  6.     return m == 0 ? 0 : (align - m) 

其他情況

基本類型按照上述方法處理就可以了,還有可選類型、數組類型、字典類型,通過遍歷、遞歸解析等方式,處理方法也類似。如數組:

  1. extension Array: ArrayTypeProtocol { 
  2.     static func getWrappedType() -> Any.Type { 
  3.         return Element.self 
  4.     } 
  5.  
  6.     static func castArrayType(arr: [Any]) -> Array<Element> { 
  7.         return arr.map({ (p) -> Element in 
  8.             return p as! Element 
  9.         }) 
  10.     } 

獲取到Array泛型實參類型,然后構造出該類型的一個數組,完成賦值就可以了。

結語

主要流程就是這樣了,也比較簡單,剩下處理繼承、組合等情況,只是實現問題,就不再贅述了。總覺得自己對Swift指針這一套設施理解還不是很到位,也許有更好的用法,比如說,完全不需要空的init()函數就可以初始化出一個類的實例。有同學在這方面有更深入理解,有什么意見或者建議的,歡迎交流~

參考

  • https://appventure.me/2015/10/24/swift-reflection-api-what-you-can-do/
  • https://www.raywenderlich.com/119881/enums-structs-and-classes-in-swift
  • http://vizlabxt.github.io/blog/2014/12/23/Swift-Memory/
  • https://realm.io/news/russ-bishop-unsafe-swift/
  • http://sketchytech.blogspot.jp/2014/10/becoming-less-afraid-of-unsafe-mutable.html
  • http://southpeak.github.io/blog/2014/07/06/ios-swift-cpointer-2/
  • https://onevcat.com/2015/01/swift-pointer/
  • https://appventure.me/2015/10/17/advanced-practical-enum-examples/
  • https://github.com/Hearst-DD/ObjectMapper
責任編輯:龐桂玉 來源: 移動開發前線
相關推薦

2016-04-11 09:58:53

iOSJSONModel

2015-10-28 09:55:39

Swift解析生產庫

2016-06-07 14:42:18

Swift設計

2015-08-14 11:37:37

Swift語言中文版

2017-02-27 16:28:00

2014-08-20 10:40:29

Xcode 6

2014-07-22 09:01:53

SwiftJSON

2022-02-25 09:03:49

工具Swift項目

2015-04-17 16:07:11

swiftOC

2010-06-30 11:16:50

SQL Server

2014-06-03 10:44:20

Swift開發語言

2015-01-12 13:04:39

Swift開源項目匯總

2014-06-04 10:52:56

Swift蘋果iOS

2015-12-07 09:46:26

swift編程開源

2023-08-28 08:40:23

Sonic開發JSON

2022-10-13 21:07:48

數據庫SQL Server

2021-04-21 00:10:12

對象JSON插件

2014-06-06 14:25:03

iOS 8SwiftWWDC2014

2015-06-09 11:12:31

Swift語言Swift特性

2014-07-29 10:49:23

Swift
點贊
收藏

51CTO技術棧公眾號

亚久久调教视频| 丁香一区二区| 亚洲精品写真福利| 国产日韩欧美综合精品| 久久亚洲精品石原莉奈 | 欧美伊人精品成人久久综合97| 亚洲精品国产精品国自产观看| 国产成人a人亚洲精品无码| 亚洲作爱视频| 久久久91精品国产一区不卡| 欧美双性人妖o0| 成人四虎影院| 午夜精品福利在线| 欧美爱爱视频网站| 欧美大片aaa| 国产老女人精品毛片久久| 91精品国产高清自在线 | 日韩精品水蜜桃| 亚洲韩国欧洲国产日产av| av污在线观看| 亚洲精品永久免费视频| 99久久综合国产精品| 欧美一区二区三区…… | 高清在线观看av| 成人动漫中文字幕| 国产综合视频在线观看| 91丝袜一区二区三区| 国产精品大片| 久久天天躁狠狠躁夜夜躁| 熟女俱乐部一区二区视频在线| 日韩免费成人| 欧美精品成人一区二区三区四区| 午夜精品久久久内射近拍高清| 日本三级韩国三级欧美三级| 中文字幕在线一区免费| 日韩精品极品视频在线观看免费| 欧美视频久久久| 国产成人亚洲综合a∨婷婷| 国产精品网红福利| 一级免费在线观看| 激情久久中文字幕| 久久99精品国产99久久6尤物| 欧美xxxooo| 日韩免费视频| 色青青草原桃花久久综合| 久久精品无码一区| 视频一区中文| 欧美久久免费观看| 国产一级不卡毛片| 日韩成人高清| 欧美性高清videossexo| av五月天在线| av在线不卡精品| 欧美制服丝袜第一页| 男人搞女人网站| 精品176极品一区| 欧美日韩成人一区二区| 一个色综合久久| 91精品一久久香蕉国产线看观看| 欧美日韩精品三区| 91看片破解版| 国模大尺度视频一区二区| 91精品国产日韩91久久久久久| 潘金莲激情呻吟欲求不满视频| 免费一级欧美在线观看视频| 884aa四虎影成人精品一区| gai在线观看免费高清| 综合欧美精品| 精品日韩一区二区三区免费视频| 亚洲成a人片在线www| 久久97精品| 亚洲欧美激情一区| 永久av免费网站| 午夜精品免费| 97欧美精品一区二区三区| 亚洲av中文无码乱人伦在线视色| 日本美女一区二区| 91免费福利视频| 亚洲精品第五页| 久久人人超碰精品| 亚洲午夜精品久久久久久浪潮| 黄a在线观看| 亚洲成人激情av| 精品视频无码一区二区三区| 日韩免费在线电影| 欧美精品一区二区三区一线天视频| 亚洲av成人无码一二三在线观看| 精品中文字幕一区二区三区av| 这里精品视频免费| 视频这里只有精品| 亚洲免费在线| 91久久久久久久一区二区| 人妻一区二区三区免费| 久久精品人人做| 在线观看18视频网站| 最近在线中文字幕| 91精品国产综合久久久久久久久久| 国产乱码一区二区三区四区| 欧美一级色片| 久色乳综合思思在线视频| 草久久免费视频| 国内精品第一页| 老司机精品福利在线观看| 大地资源网3页在线观看| 疯狂欧美牲乱大交777| 色91精品久久久久久久久| 老司机精品在线| 久久精品小视频| 亚洲av无码精品一区二区| 福利一区二区在线| 亚洲天堂电影网| 自拍视频在线看| 欧美变态tickle挠乳网站| 久久久视频6r| 欧美区日韩区| 国产日韩欧美电影在线观看| 日本私人网站在线观看| 一区二区三区不卡视频在线观看| 丰满少妇在线观看| 性欧美lx╳lx╳| 欧美激情啊啊啊| 国产麻豆精品一区| 亚洲国产精品二十页| 蜜桃传媒一区二区三区| 精品视频91| 日韩中文字幕网| 无码人妻一区二区三区线| www.欧美日韩国产在线| 青青视频免费在线| 国产精品一区二区三区av | youjizz亚洲女人| 国产美女一区| 狠狠色综合欧美激情| 伊人222成人综合网| 欧美美女bb生活片| 免费成人深夜天涯网站| 日韩va亚洲va欧美va久久| 久久狠狠久久综合桃花| 2020国产在线| 亚洲国产精品久久久久秋霞不卡| 三级黄色片在线观看| 青青草视频一区| 色一情一区二区三区四区| 亚洲最新无码中文字幕久久| 亚洲精品国精品久久99热| 国产黄色片视频| caoporm超碰国产精品| 999一区二区三区| 国产亚洲成av人片在线观黄桃| 欧美激情乱人伦一区| 亚洲AV午夜精品| 一区二区三区免费在线观看| 国产亚洲色婷婷久久| 午夜精品久久久久99热蜜桃导演| 99re视频在线| 影院在线观看全集免费观看| 日韩欧美国产电影| 在线免费观看毛片| 91在线高清观看| 黄在线观看网站| 成人综合一区| 91久久久久久| 丁香高清在线观看完整电影视频| 精品国内片67194| 国产精品999在线观看| 久久婷婷综合激情| 午夜免费福利在线| 91成人精品| 国产精品夜夜夜一区二区三区尤| 超碰91在线观看| 亚洲最大在线视频| 国产美女无遮挡永久免费| 亚洲一区国产视频| 久久精品国产亚洲AV熟女| 蜜臀精品一区二区三区在线观看 | 欧美无砖砖区免费| 91 在线视频| 粉嫩欧美一区二区三区高清影视 | 久久久久久久久久久网| av亚洲精华国产精华| 国产激情在线观看视频| 99精品在线| 国产一区二区三区色淫影院| 日韩精品影片| 色综合久久悠悠| 日本一二三区在线视频| 欧美日本一区二区三区四区| 国产大片aaa| 欧美激情中文不卡| 99免费观看视频| 奇米色一区二区| 欧美日韩激情四射| 欧美精品尤物在线观看| 超碰97在线播放| 成人国产精品| 国外成人在线视频| 久久精品视频观看| 亚洲精品一二区| 国内老熟妇对白xxxxhd| 日本高清免费不卡视频| 激情四射综合网| 国产精品色呦呦| 国产精品一区二区入口九绯色| 久久精品99国产国产精| 国产免费毛卡片| 欧美一区二区| 日韩欧美一区二区在线观看 | 亚洲成人a**址| 精品国产18久久久久久洗澡| 国产在线观看91精品一区| 国产资源在线观看入口av| 久久这里只有精品99| 国模精品一区二区| 亚洲国产另类久久精品| 国产精品一级视频| 欧洲国内综合视频| 日韩 欧美 中文| 亚洲一区二区欧美激情| 最新一区二区三区| 国产精品传媒视频| 亚洲第一综合网| 久久亚洲影视婷婷| 国产激情第一页| 国产寡妇亲子伦一区二区| 日本中文字幕精品—区二区| 日韩专区欧美专区| 日韩精品一区二区三区久久| 狠狠入ady亚洲精品经典电影| 欧美 另类 交| 99精品国产一区二区三区| 日韩av在线电影观看| 婷婷精品在线| 九九九九九精品| 欧美男人操女人视频| 高清国产一区| xxxx日韩| 国产九色精品| 136福利精品导航| av一区和二区| 豆花视频一区二区| 精品国产一区二区三区久久久久久| 天堂久久av| 成人黄视频免费| 国产成人精品福利| 精品乱色一区二区中文字幕| 精品一区二区男人吃奶| 国产一区二区不卡视频| 你懂的在线观看一区二区| 久久亚洲精品欧美| 久久av免费看| 水蜜桃一区二区| 色小子综合网| 可以在线看黄的网站| 黄色av日韩| 各处沟厕大尺度偷拍女厕嘘嘘| 国产精品美女| 三级在线视频观看| 精品无码三级在线观看视频| 加勒比av中文字幕| 国产69精品久久久久777| 欧美xxxxx精品| 久久婷婷色综合| 中文字幕第69页| 亚洲综合免费观看高清完整版| 精品在线免费观看视频| 午夜av一区二区三区| 国产伦精品一区二区三区视频网站| 色婷婷久久久久swag精品| 中文字幕一区2区3区| 欧美一区二区在线播放| 丰满熟妇人妻中文字幕| 日韩精品亚洲元码| 番号集在线观看| 欧美精品中文字幕一区| 99在线视频影院| 国产99久久精品一区二区| 亚洲毛片在线免费| 国产精品二区三区四区| 九九精品在线| 国产91视频一区| 久久电影一区| 超碰中文字幕在线观看| 99精品桃花视频在线观看| 69精品无码成人久久久久久| 亚洲欧洲综合另类| 国产毛片aaa| 欧美一区二区三区在线视频| 色婷婷综合视频| www.久久久久| 蜜桃视频m3u8在线观看| 国产区亚洲区欧美区| 99a精品视频在线观看| 日韩福利一区二区三区| 国产伊人精品| 日日干夜夜操s8| 91麻豆蜜桃一区二区三区| 久久福利免费视频| 色综合色狠狠综合色| 999久久久久久| 国产亚洲综合久久| 美女精品视频| 91精品国产综合久久久久久久久 | 亚洲人一区二区| 日韩视频一区二区三区在线播放免费观看| 99视频免费播放| av不卡在线观看| 18岁成人毛片| 欧美日韩在线亚洲一区蜜芽| 狠狠综合久久av一区二区| 日韩亚洲欧美成人| 欧美亚洲韩国| 久久99精品久久久久久水蜜桃| 66视频精品| 香港日本韩国三级网站| 2021久久国产精品不只是精品| 天天看片中文字幕| 欧美日韩在线综合| 东热在线免费视频| 欧美中文字幕在线| 精品国产导航| 欧美高清中文字幕| 国产一区二区h| 免费看一级黄色| 色老综合老女人久久久| 天天干天天色天天| 久久久久九九九九| 久久精品九色| 99亚洲精品视频| 卡一卡二国产精品| www久久久久久久| 91国在线观看| 青青青草网站免费视频在线观看| 欧美激情免费视频| av不卡一区二区| 男人天堂av片| 成人综合婷婷国产精品久久免费| 日本福利片在线观看| 欧美久久久久久蜜桃| 欧美午夜电影一区二区三区| 国产精品午夜一区二区欲梦| 精品毛片免费观看| 天天爽人人爽夜夜爽| 国产欧美日韩视频在线观看| 亚洲色成人www永久网站| 亚洲欧美成人一区二区在线电影| 少妇视频一区| 日产精品久久久一区二区| 久久久噜噜噜| 免费一级黄色录像| 欧美日韩精品高清| 国产原创在线观看| 亚洲一区二区三区久久| 中文字幕亚洲精品乱码| jjzz黄色片| 精品成人乱色一区二区| 香港三日本三级少妇66| 日韩女优在线播放| 日韩www.| 色男人天堂av| 一二三区精品视频| 网站黄在线观看| 国产999在线| 911久久香蕉国产线看观看| 国产精品嫩草69影院| 欧美日韩国产激情| 你懂的视频在线播放| 国产精品视频一区国模私拍| 国产精品99在线观看| 久久久久久久久久影视| 欧美午夜精品久久久久久人妖| 国产九九在线| 亚洲aⅴ日韩av电影在线观看 | 在线日韩网站| 国产一伦一伦一伦| 亚洲国产精品久久久久婷婷884 | 久久97久久97精品免视看| 久久资源综合| 男人插女人下面免费视频| 亚洲天堂久久久久久久| 天堂av中文字幕| 国产精品久久视频| 国内精品久久久久久久97牛牛 | 亚洲性感美女99在线| 国产特黄级aaaaa片免| 欧美日韩国产欧美日美国产精品| 污污的网站在线看| 欧美性bbwbbwbbwhd| 寂寞少妇一区二区三区| 日韩成人一区二区三区| 在线观看国产精品日韩av| 亚洲高清999| 婷婷丁香激情网| 一区二区三区在线视频播放| 黄色在线播放| 波多野结衣一区二区三区在线观看| 亚洲一区国产| 青青草原在线免费观看视频| 亚洲性视频网站| 国产精品xxx在线观看| 在线观看国产中文字幕|