2017-09-26 1 views
0

나는 장소중첩 된 JSON 문자열을 Swift에서 객체로 구문 분석하는 방법은 무엇입니까?

struct Symbol : Codable { 
    let id:Int 
    let type:String 
    let properties:[String:String]? 
} 

struct Event : Codable { 
    let event:String 
    let timestamp:Int 
    let symbol:Symbol? 
} 

struct LogRow : Codable { 
    let id:Int 
    let user_id:String 
    let question_id:String 
    let actions:[Event] 
    let timestamp:Double 
} 

하고 다음 JSON 배열

[ 
    { 
    "id": 26535754, 
    "user_id": "qhv1i39wsmbkzhjiffk1rrsg", 
    "question_id": "\"trapdoor|186752c1-948e-4c15-b3df-7d39a99fe9d6\"", 
    "actions": "[{\"event\": \"OPEN\", \"timestamp\": 1499802241640}, {\"event\": \"DRAG_START\", \"symbol\": {\"id\": 15, \"type\": \"Fn\", \"properties\": {\"name\": \"cos\", \"allowSubscript\": true, \"innerSuperscript\": true}}, \"timestamp\": 1499802243567}, {\"event\": \"UNDOCK_SYMBOL\", \"parent\": {\"id\": 14, \"type\": \"Fraction\"}, \"symbol\": {\"id\": 15, \"type\": \"Fn\", \"properties\": {\"name\": \"cos\", \"allowSubscript\": true, \"innerSuperscript\": true}}, \"timestamp\": 1499802243567, \"dockingPoint\": \"right\"}, {\"event\": \"DOCK_SYMBOL\", \"parent\": {\"id\": 13, \"type\": \"Fraction\"}, \"symbol\": {\"id\": 15, \"type\": \"Fn\", \"properties\": {\"name\": \"cos\", \"allowSubscript\": true, \"innerSuperscript\": true}}, \"timestamp\": 1499802243699, \"dockingPoint\": \"denominator\"}, {\"event\": \"DRAG_START\", \"symbol\": {\"id\": 16, \"type\": \"Num\", \"properties\": {\"significand\": \"60\"}}, \"timestamp\": 1499802244570}, {\"event\": \"UNDOCK_SYMBOL\", \"parent\": {\"id\": 15, \"type\": \"Fn\", \"properties\": {\"name\": \"cos\", \"allowSubscript\": true, \"innerSuperscript\": true}}, \"symbol\": {\"id\": 16, \"type\": \"Num\", \"properties\": {\"significand\": \"60\"}}, \"timestamp\": 1499802244570, \"dockingPoint\": \"argument\"}, {\"event\": \"DROP_SYMBOL\", \"symbol\": {\"id\": 16, \"type\": \"Num\", \"properties\": {\"significand\": \"60\"}}, \"timestamp\": 1499802245281}, {\"event\": \"DRAG_START\", \"symbol\": {\"id\": 13, \"type\": \"Fraction\"}, \"timestamp\": 1499802245845}, {\"event\": \"TRASH_SYMBOL\", \"symbol\": {\"id\": 13, \"type\": \"Fraction\"}, \"timestamp\": 1499802246826}, {\"event\": \"DRAG_START\", \"symbol\": {\"id\": 16, \"type\": \"Num\", \"properties\": {\"significand\": \"60\"}}, \"timestamp\": 1499802247468}, {\"event\": \"TRASH_SYMBOL\", \"symbol\": {\"id\": 16, \"type\": \"Num\", \"properties\": {\"significand\": \"60\"}}, \"timestamp\": 1499802248360}, {\"event\": \"DRAG_START\", \"symbol\": {\"id\": 19, \"type\": \"Num\", \"properties\": {\"significand\": \"2\"}}, \"timestamp\": 1499802249161}, {\"event\": \"UNDOCK_SYMBOL\", \"parent\": {\"id\": 14, \"type\": \"Fraction\"}, \"symbol\": {\"id\": 19, \"type\": \"Num\", \"properties\": {\"significand\": \"2\"}}, \"timestamp\": 1499802249161, \"dockingPoint\": \"denominator\"}, {\"event\": \"DOCK_SYMBOL\", \"parent\": {\"id\": 14, \"type\": \"Fraction\"}, \"symbol\": {\"id\": 19, \"type\": \"Num\", \"properties\": {\"significand\": \"2\"}}, \"timestamp\": 1499802249289, \"dockingPoint\": \"denominator\"}, {\"event\": \"DRAG_START\", \"symbol\": {\"id\": 19, \"type\": \"Num\", \"properties\": {\"significand\": \"2\"}}, \"timestamp\": 1499802249797}, {\"event\": \"UNDOCK_SYMBOL\", \"parent\": {\"id\": 14, \"type\": \"Fraction\"}, \"symbol\": {\"id\": 19, \"type\": \"Num\", \"properties\": {\"significand\": \"2\"}}, \"timestamp\": 1499802249797, \"dockingPoint\": \"denominator\"}, {\"event\": \"DOCK_SYMBOL\", \"parent\": {\"id\": 14, \"type\": \"Fraction\"}, \"symbol\": {\"id\": 19, \"type\": \"Num\", \"properties\": {\"significand\": \"2\"}}, \"timestamp\": 1499802249906, \"dockingPoint\": \"denominator\"}, {\"event\": \"DRAG_POTENTIAL_SYMBOL\", \"symbol\": {\"id\": 20, \"type\": \"Num\", \"properties\": {\"significand\": \"4\"}}, \"timestamp\": 1499802251451}, {\"event\": \"DROP_POTENTIAL_SYMBOL\", \"symbol\": {\"id\": 20, \"type\": \"Num\", \"properties\": {\"significand\": \"4\"}}, \"timestamp\": 1499802254229}, {\"event\": \"DRAG_START\", \"symbol\": {\"id\": 19, \"type\": \"Num\", \"properties\": {\"significand\": \"2\"}}, \"timestamp\": 1499802255231}, {\"event\": \"UNDOCK_SYMBOL\", \"parent\": {\"id\": 14, \"type\": \"Fraction\"}, \"symbol\": {\"id\": 19, \"type\": \"Num\", \"properties\": {\"significand\": \"2\"}}, \"timestamp\": 1499802255231, \"dockingPoint\": \"denominator\"}, {\"event\": \"TRASH_SYMBOL\", \"symbol\": {\"id\": 19, \"type\": \"Num\", \"properties\": {\"significand\": \"2\"}}, \"timestamp\": 1499802256593}, {\"event\": \"DRAG_START\", \"symbol\": {\"id\": 20, \"type\": \"Num\", \"properties\": {\"significand\": \"4\"}}, \"timestamp\": 1499802257376}, {\"event\": \"DOCK_SYMBOL\", \"parent\": {\"id\": 14, \"type\": \"Fraction\"}, \"symbol\": {\"id\": 20, \"type\": \"Num\", \"properties\": {\"significand\": \"4\"}}, \"timestamp\": 1499802258062, \"dockingPoint\": \"denominator\"}, {\"event\": \"CLOSE\", \"timestamp\": 1499802259093}]", 
    "timestamp": 1.499802259277E9 
    }, 
    { 
    "id": 26535718, 
    "user_id": "qhv1i39wsmbkzhjiffk1rrsg", 
    "question_id": "\"trapdoor|186752c1-948e-4c15-b3df-7d39a99fe9d6\"", 
    "actions": "[{\"event\": \"OPEN\", \"timestamp\": 1499802175061}, {\"event\": \"DRAG_POTENTIAL_SYMBOL\", \"symbol\": {\"id\": 10, \"type\": \"Fraction\"}, \"timestamp\": 1499802178936}, {\"event\": \"DOCK_POTENTIAL_SYMBOL\", \"parent\": {\"id\": 7, \"type\": \"Symbol\", \"properties\": {\"letter\": \"g\"}}, \"symbol\": {\"id\": 10, \"type\": \"Fraction\"}, \"timestamp\": 1499802183785, \"dockingPoint\": \"subscript\"}, {\"event\": \"DRAG_START\", \"symbol\": {\"id\": 10, \"type\": \"Fraction\"}, \"timestamp\": 1499802184864}, {\"event\": \"UNDOCK_SYMBOL\", \"parent\": {\"id\": 7, \"type\": \"Symbol\", \"properties\": {\"letter\": \"g\"}}, \"symbol\": {\"id\": 10, \"type\": \"Fraction\"}, \"timestamp\": 1499802184865, \"dockingPoint\": \"subscript\"}, {\"event\": \"DOCK_SYMBOL\", \"parent\": {\"id\": 6, \"type\": \"Symbol\", \"properties\": {\"letter\": \"m\"}}, \"symbol\": {\"id\": 10, \"type\": \"Fraction\"}, \"timestamp\": 1499802185857, \"dockingPoint\": \"subscript\"}, {\"event\": \"DRAG_START\", \"symbol\": {\"id\": 10, \"type\": \"Fraction\"}, \"timestamp\": 1499802186710}, {\"event\": \"UNDOCK_SYMBOL\", \"parent\": {\"id\": 6, \"type\": \"Symbol\", \"properties\": {\"letter\": \"m\"}}, \"symbol\": {\"id\": 10, \"type\": \"Fraction\"}, \"timestamp\": 1499802186710, \"dockingPoint\": \"subscript\"}, {\"event\": \"DROP_SYMBOL\", \"symbol\": {\"id\": 10, \"type\": \"Fraction\"}, \"timestamp\": 1499802188430}, {\"event\": \"DRAG_POTENTIAL_SYMBOL\", \"symbol\": {\"id\": 11, \"type\": \"Fraction\"}, \"timestamp\": 1499802194665}, {\"event\": \"DROP_POTENTIAL_SYMBOL\", \"symbol\": {\"id\": 11, \"type\": \"Fraction\"}, \"timestamp\": 1499802195427}, {\"event\": \"DRAG_START\", \"symbol\": {\"id\": 6, \"type\": \"Symbol\", \"properties\": {\"letter\": \"m\"}}, \"timestamp\": 1499802196167}, {\"event\": \"DOCK_SYMBOL\", \"parent\": {\"id\": 11, \"type\": \"Fraction\"}, \"symbol\": {\"id\": 6, \"type\": \"Symbol\", \"properties\": {\"letter\": \"m\"}}, \"timestamp\": 1499802197167, \"dockingPoint\": \"numerator\"}, {\"event\": \"DRAG_START\", \"symbol\": {\"id\": 8, \"type\": \"Fn\", \"properties\": {\"name\": \"cos\", \"allowSubscript\": true, \"innerSuperscript\": true}}, \"timestamp\": 1499802198247}, {\"event\": \"UNDOCK_SYMBOL\", \"parent\": {\"id\": 7, \"type\": \"Symbol\", \"properties\": {\"letter\": \"g\"}}, \"symbol\": {\"id\": 8, \"type\": \"Fn\", \"properties\": {\"name\": \"cos\", \"allowSubscript\": true, \"innerSuperscript\": true}}, \"timestamp\": 1499802198247, \"dockingPoint\": \"right\"}, {\"event\": \"DOCK_SYMBOL\", \"parent\": {\"id\": 11, \"type\": \"Fraction\"}, \"symbol\": {\"id\": 8, \"type\": \"Fn\", \"properties\": {\"name\": \"cos\", \"allowSubscript\": true, \"innerSuperscript\": true}}, \"timestamp\": 1499802199971, \"dockingPoint\": \"right\"}, {\"event\": \"DRAG_START\", \"symbol\": {\"id\": 11, \"type\": \"Fraction\"}, \"timestamp\": 1499802201551}, {\"event\": \"DROP_SYMBOL\", \"symbol\": {\"id\": 11, \"type\": \"Fraction\"}, \"timestamp\": 1499802202638}, {\"event\": \"DRAG_POTENTIAL_SYMBOL\", \"symbol\": {\"id\": 12, \"type\": \"Num\", \"properties\": {\"significand\": \"2\"}}, \"timestamp\": 1499802209025}, {\"event\": \"DOCK_POTENTIAL_SYMBOL\", \"parent\": {\"id\": 11, \"type\": \"Fraction\"}, \"symbol\": {\"id\": 12, \"type\": \"Num\", \"properties\": {\"significand\": \"2\"}}, \"timestamp\": 1499802210771, \"dockingPoint\": \"denominator\"}, {\"event\": \"CLOSE\", \"timestamp\": 1499802212398}]", 
    "timestamp": 1.49980221259E9 
    } 
] 

JSON 데이터가 DataGrip의 JSON 수출을 통해 수출 데이터베이스에서 제공에 다음과 같은 데이터 구조를 가지고있다. 데이터베이스 필드는 JSON Blob 유형입니다 (Postgres이므로 괜찮습니다). (예, 나는 또한, 차이를 하나의 화살표 버전을 시도하지) 경우

SELECT 
    ... 
    event_details->>'actions' AS actions, 
    ... 
FROM yadda_yadda...; 

가 유용 : 쿼리는 같은입니다.

내 질문은 actions 문자열을 JSON 객체로 [Event]에 구문 분석하려면 어떻게해야합니까? 또는, DataGrip (또는 postgres)에서 해당 필드를 직렬화 된 객체가 아닌 컨테이너와 같은 객체로 내보내는 방법이 있습니까? 더 이상하지 LogRow

편집 나는이

struct LogRow : Codable { 
    let id:Int 
    let user_id:String 
    let question_id:String 
    let actions:[Event] 
    let timestamp:Double 

    enum CodingKeys: String, CodingKey { 
     case id 
     case user_id 
     case question_id 
     case actions 
     case timestamp 
    } 

    init(from decoder: Decoder) throws { 
     let values = try decoder.container(keyedBy: CodingKeys.self) 
     id = try values.decode(Int.self, forKey: .id) 
     user_id = try values.decode(String.self, forKey: .user_id) 
     question_id = try values.decode(String.self, forKey: .question_id) 
     timestamp = try values.decode(Double.self, forKey: .timestamp) 

     let actions_string = try values.decode(String.self, forKey: .actions) 
     let actions_data = actions_string.data(using: .utf8)! 
     actions = try JSONDecoder().decode([Event].self, from: actions_data) 
    } 
} 

같은 LogRow을 변경하고 지금은 이전에 비슷한 오류를 받고 있어요,하지만 분명히 Event합니다.

fatal error: Error raised at top level: 
Swift.DecodingError.typeMismatch(Swift.String, 
Swift.DecodingError.Context(codingPath: [Foundation.(_JSONKey in 
_12768CA107A31EF2DCE034FD75B541C9)(stringValue: "Index 1", intValue: 
Optional(1)), tree_builder.Event.(CodingKeys in 
_D5964B2C6A943A986EE24818C2C63D9B).symbol, tree_builder.Symbol. 
(CodingKeys in _D5964B2C6A943A986EE24818C2C63D9B).properties, 
Swift._DictionaryCodingKey(stringValue: "allowSubscript", intValue: 
nil)], debugDescription: "Expected to decode String but found a number 
instead.", underlyingError: nil)): file 
/Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang- 
900.0.65/src/swift/stdlib/public/core/ErrorType.swift, line 187 
이 애플에 의해 주어진 솔루션입니다
+0

먼저이 모든 암시 적으로 래핑되지 않은 선택 사항을 제거해야합니다. 이 대답은 그것을 성취하는 방법을 보여줍니다. https://stackoverflow.com/a/43121890/2303865 –

+0

평소와 달리, 나는 환경을 완벽하게 통제하므로 내 선택 물을 내재적으로 사용하지 않을 수 있음을 확신합니다. 데이터 세트. 내가 야생에서 이것을 풀어 준다면 나는 그것을 분명히 없애 버릴 것이다. – Morpheu5

+2

당신이 할 수 있거나 할 수 없다면 요점은 아닙니다. 너는 필요 없어. –

답변

1
당신은 선택 체인을 사용할 수 있습니다

: https://github.com/Hearst-DD/ObjectMapper처럼, 당신을 위해 그것을하지 라이브러리 또는 https://github.com/tristanhimmelman/AlamofireObjectMapper

도있다 https://developer.apple.com/swift/blog/?id=37

이가 기본적인 예는이 어떻게 그것을 할 수 있습니다,하지만 당신은 리팩토링 내가 준 링크에서 살펴해야 :

guard let event = jsonObject["event"] as? String, let timestamp = jsonObject["timestamp"] as? Int else {return} 
myEvent.event = event 
myEvent.timestamp = timestamp 
if let symbol = jsonObject["symbol"] as? [String:Any] { 
    guard let symbolId = symbol["id"] as? Int, let type = symbol["type"] else {return} 
    let mySymbol = symbol() 
    mySymbol.id = id 
    mySymbol.type = type 
} 

편집

당신은 정말 쉽게해야 빠른 4 Codable 프로토콜을 사용하는 경우, 당신은 너무 Codable 같은 중첩 된 개체를 확인해야합니다! 그렇다면 단지 :

try decoder.decode(yourType.self, from: yourJsonString) 

정확하게 CodingKeys를 사용한다면 올바르게 처리해야합니다.

+0

Uuuh, 내 질문은 json 문자열을 객체로 디코딩하는 방법이 아니 었습니다. 테스트 문자열을 디코더에 공급하고'Event' 객체를 내뱉도록 요청하면 작동합니다. 내 질문은 : 직렬화 된'LogRow'가'actions' 키에'Event' 배열의 직렬화 된 표현을 포함하는 문자열을 포함하고 있다면, 어떻게 그 문자열을 디시리얼라이저로 만들고 그것을' 이벤트's? – Morpheu5

+0

https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types –

관련 문제