Chaim Friedman Chaim Friedman - 23 days ago 5x
iOS Question

One French character in a JSON file crashes it all

I am outputting stuff from a JSON file that is parsed from a MySQL database using PHP. It contains user-inputed data. I know that the JSON is valid because I test it in a standard JSON validator and am being told: The JSON input is valid according to RFC 4627 (JSON specfication)

I retrieve the code in my iOS app (Swift) using JSONObjectWithData as shown below.

Problem I'm having is that I only need one customer that types his name as Jürgensen, and my whole list is now broken in my app! Instead of a list of names I get a blank table. The JSON file is STILL valid, I see those characters nicely displayed if I run my JSON file directly in browser so I think it's UTF 8 compliant. To be on the safe side I'm making sure the code is compliant UTF8 wise on the PHP side as well using mysql_set_charset('utf8', $query) on my MySQL query.
(Also above JSON validator test as above test is still ok).

So my problem must be on my Xcode side, which is the following:

let url = NSURL(string: "")

println("so far so good 1")

if let JSONData = NSData(contentsOfURL: url!)

println("so far so good 2")

if let json = NSJSONSerialization.JSONObjectWithData(JSONData, options: nil, error: nil) as? NSDictionary

println("so far so good 3")

if let PeopleArray = json["people"] as? [NSDictionary]

and so on...

As I want to see which part of my Swift code is choking, I am outputting those messages to the console. When I have a French character in the file I only get past "so far so good 2". That tells me it's either NSJSONSerialization or JSONObjectWithData (or possibly both?) that is my problem.


This would be a sample of Json code that would not work because of a single French character:

{"people":[ {"fname”:”Brenda ", "lname”:”Jones”, "dotrav":"2015-07-21”, "payment_description":"Cash”, "amount_paid”:”20.00", "showed_up":"0", "numofseats”:”2”, "resnum”:”1152A057733jh6541", "res_id”:”52628939", "res_notes”:””},{“fname”:”John”, "lname":"Jürgensen", "dotrav":"2015-07-23", "payment_description":"Credit Card", "amount_paid":"30.00", "showed_up":"0", "numofseats":"2", "resnum":"3434A8989835463J2", "res_id":"52628940”, "res_notes”:”Nothing special in notes”} ]}


You should update your code to Log the error - Looks like you are having trouble with the NSError -- I'm all ObjC - but I think this is more correct in Swift.

var jsonError: NSError?
let jsonResponse: AnyObject? = NSJSONSerialization.JSONObjectWithData(jsonData!, options:NSJSONReadingOptions(), error: &jsonError)
if (jsonError != nil) {


I've created a playground that may help clarify what I'm assuming is happening - an encoding problem - where something is misidentifying or converting data from one character encoding to another. You will need to ensure that the server you are downloading json from is encoding the data properly before sending - you can print out the bytes from the data following the example I have below - to check to see if the bytes coming from the server are correct - for easy of debugging - you may want to reduce the problem to a very minimal example.

//: Playground - noun: a place where people can play

// Updated to xcode 7 & swift 2.0

import UIKit

// put a string in an array
let uUmlautArray = ["ü"]

var error:NSError?

// testData will represent utf-8 encoded
var testData:NSData?

do {
    testData = try NSJSONSerialization.dataWithJSONObject(uUmlautArray, options: NSJSONWritingOptions())
} catch let error as NSError {

// a u+umlaut should encode as
// 5b = left square bracket
// 22 = double quote
// c3bc - since it's utf8 encoded - NSJSONSerialization reads/writes data as UTF8 encoded data
// 22 = double quote
// 5d = right square bracket


// same string represented as UTF-8 with u+umlaut = 0xc3, 0xbc
var utf8EncodedData = NSData(bytes: [0x5b, 0x22, 0xc3, 0xbc, 0x22, 0x5d] as [UInt8], length: 6)
var json:AnyObject?

do {
    json = try NSJSONSerialization.JSONObjectWithData(utf8EncodedData, options:NSJSONReadingOptions())
} catch let error as NSError{

// same string encoded with latin-1 with u+umlaut = 0xfc
var latin1EncodedData = NSData(bytes: [0x5b, 0x22, 0xfc, 0x22, 0x5d] as [UInt8], length: 5)
var json2: AnyObject?
do {
    json2 = try NSJSONSerialization.JSONObjectWithData(latin1EncodedData, options:NSJSONReadingOptions())
}  catch let error as NSError{

// server returned an invalid JSON string - it must be UTF-8 encoded - the equivalent code really should
// be done by the server

var convertString:NSString
convertString = NSString.init(data: latin1EncodedData, encoding: NSWindowsCP1250StringEncoding)!

// converted data
var convertedData = convertString.dataUsingEncoding(NSUTF8StringEncoding);

do {
    json = try NSJSONSerialization.JSONObjectWithData(convertedData!, options:NSJSONReadingOptions())
} catch let error as NSError{