Daily 2018-12-27

TIL

swift

오전: 강의

오후 : 제이슨파서

//
//  Parser.swift
//  JSONParser
//
//  Created by Elena on 27/12/2018.
//  Copyright © 2018 elena. All rights reserved.
//

import Foundation
//JSON 출력을 위한 Protocol
protocol JSONResult {
    var resultDataPrint: String { get }
    var parserResultPrint: String { get }
    
}

extension String {
    func splitByComma() -> [String] {
        return self.split(separator: ",").map({String($0)})
    }
    func removeBothFirstAndLast() -> String {
        return String(self.dropFirst().dropLast())
    }
    func splitByColon() -> [String] {
        return self.split(separator: ":").map({String($0)})
    }
}

struct Parser{
    // 입력받은 데이터를 분석해서 반환
    static func DivideData(from data: String) -> JSONData? {
        guard isDivideData(from: data) else {
            return nil
        }
        // 대괄호가 나오면 Array로 괄호 갯수만 세서 출력하는걸로 
        if data.first?.description == "[" {
            return parseBracket(data)
        }
        // 객체일 경우 파싱할수 있도록
        let datasJSON = parserForm(data)
        var parseJSONData = parseDatas(datasJSON)
        parseJSONData?.datas = data.splitByComma()
        return parseJSONData
    }
    // 열린괄호랑 닫힌 괄호랑 같은지 판별한다음 갯수를 저장해서 반환
    private static func parseBracket(_ data: String) -> JSONData? {
        var resultData: JSONData = JSONData()
        var leftBracket = 0
        var rightBracket = 0
        leftBracket = data.components(separatedBy: "{").count
        rightBracket = data.components(separatedBy: "}").count
        if leftBracket != rightBracket {
            return nil
        }
        resultData.objectCount = leftBracket-1
        return resultData
    }
    // Form 만들기
    private static func parserForm(_ data: String) -> [String:String]{
        var dicFormData = [String:String]()
        var dataSplitByComma: [String] = data.splitByComma()
        for index in 0..<dataSplitByComma.count {
            // 괄호를 일단 지우고 데이터를 딕셔너리로 파싱을 한다.
            if dataSplitByComma[index].first?.description == "{" {
                let bracket = dataSplitByComma[index].dropFirst()
                dataSplitByComma[index] = String(bracket)
                
            }else if dataSplitByComma[index].last?.description == "}" {
                let bracket = dataSplitByComma[index].dropLast()
                dataSplitByComma[index] = String(bracket)
            }
            var dataSplitByColon = dataSplitByComma[index].splitByColon()
            dicFormData.updateValue(dataSplitByColon[1], forKey: dataSplitByColon[0])
        }
        return dicFormData
    }
    // 딕셔너리를 받아서 value있는 값을 파싱한다.
    private static func parseDatas(_ data: [String:String]) -> JSONData?{
        var resultData: JSONData = JSONData()
        for (_,value) in data {
            let value = value.trimmingCharacters(in: .whitespacesAndNewlines)
            
            if isStringType(value) {
                resultData.dataString.append(value)
            }else if isBoolType(value) {
                guard let isData = Bool(value) else { break }
                resultData.dataBool.append(isData)
            }else if isNumber(value) && isValidCharacter(value) {
                guard  let isData = Int(value) else{ break }
                resultData.dataInt.append(isData)
            }
        }
        return resultData
    }
    
    // 입력받은 데이터에 괄호가 있는지 체크
    static func isDivideData(from data: String) -> Bool {
        if (data.first?.description) == "{" , data.last?.description == "}" {
            return true
        }
        guard ((data.first?.description) == "["), ((data.last?.description) == "]") else {
            return false
        }
        return true
    }
    
    private static func isNumber (_ popData : String) -> Bool {
        return popData.components(separatedBy: CharacterSet.decimalDigits).count != 0
    }
    private static func isValidCharacter(_ popData : String) -> Bool {
        let validCharacter = CharacterSet.init(charactersIn: "0123456789")
        return (popData.rangeOfCharacter(from: validCharacter.inverted) == nil)
    }
    
    private static func isStringType (_ popData : String) -> Bool {
        return popData.first == "\"" && popData.last == "\""
    }
    
    private static func isBoolType (_ popData : String) -> Bool {
        return popData.contains("true") || popData.contains("false")
    }
}

Written on December 27, 2018