Reputation: 6022
I have the following code for handling JSON easier. However I get an compiler error in debug as well as release mode: Command failed due to signal: Segmentation fault 11
. The line where the compiler apparently fails compiling is the first line of the initialization method. I also tried several different ways (nested function, assigning the closure to another variable first and so on) but the compiler wasn't able to get it to work. Is there any way to fix this? Thanks for your help
enum JSONValue {
case JSONString(String)
case JSONNumber(Double)
case NIL(NilLiteralConvertible)
case JSONArray(Array<JSON>)
case JSONDictionary(Dictionary<String, JSON>)
}
struct JSON {
private let value: JSONValue
init(_ object: AnyObject?) {
value = { () -> JSONValue in
switch object {
case _ where object is String:
return .JSONString(object as! String)
case _ where object is NSNumber:
return .JSONNumber((object as! NSNumber).doubleValue)
case _ where object is Array<AnyObject>:
var array = [JSON]()
let original = object as! [AnyObject]
for item in original {
array += [JSON(item)]
}
return .JSONArray(array)
case _ where object is [String: AnyObject]:
var dictionary = [String: JSON]()
let original = object as! [String: AnyObject]
for item in original {
dictionary[item.0] = JSON(item.1)
}
return .JSONDictionary(dictionary)
default:
return .NIL(nil)
}
}()
}
var dictionaryKeyArray: [String] {
switch self.value {
case .JSONDictionary(let dictionary):
var result = [String]()
for item in dictionary.keys {
result.append(item)
}
return result
default:
fatalError("no dictionary")
}
}
var jsonArray: [JSON] {
switch self.value {
case .JSONArray(let array):
return array
default:
fatalError("no array")
}
}
var stringArray: [String] {
switch self.value {
case .JSONArray(let array):
var result = [String]()
for item in array {
result.append(item.stringValue)
}
return result
default:
fatalError("no string array")
}
}
var doubleValue: Double {
switch self.value {
case .JSONNumber(let double):
return double
default:
fatalError("no double value")
}
}
var intValue: Int {
switch self.value {
case .JSONNumber(let int):
return Int(int)
default:
fatalError("no integer value")
}
}
var stringValue: String {
switch self.value {
case .JSONString(let string):
return string
default:
fatalError("no string value")
}
}
var isNil: Bool {
switch self.value {
case .NIL(_):
return true
default:
return false
}
}
subscript(index: Int) -> JSON {
switch self.value {
case .JSONArray(let array) where array.count < index:
return array[index]
default:
return JSON(nil)
}
}
subscript(key: String) -> JSON {
switch self.value {
case .JSONDictionary(let dictionary) where dictionary[key] != nil:
return dictionary[key]!
default:
return JSON(nil)
}
}
}
Upvotes: 1
Views: 93
Reputation: 539975
The compiler should not segfault, no matter how wrong the source code is, so you could write a bug report to Apple in any case.
But the problem is that defining
enum JSONValue {
// ...
case NIL(NilLiteralConvertible)
// ...
}
does not mean that JSONValue.NIL(nil)
is a valid enumeration value.
Types conforming to NilLiteralConvertible
are those which can be
initialized with nil
, for example optionals:
let opt : Int? = nil
So JSONValue.NIL(Optional<Int>(0))
would be a valid enumeration value. But that is probably not what you wanted.
I think you should just define the enumeration as
enum JSONValue {
case JSONString(String)
case JSONNumber(Double)
case NIL // <- instead of NIL(NilLiteralConvertible)
case JSONArray(Array<JSON>)
case JSONDictionary(Dictionary<String, JSON>)
}
and then replace .NIL(nil)
by .NIL
in your code. At least it
does compile with this change.
Upvotes: 1