Search code examples
jsonswiftnsdictionary

“Old-Style ASCII Property List” to Json in Swift


I have a string that looks like following:

{\n    \"account_no\" = \"5675672343244\";\n    \"account_kind\" =     {\n        \".tag\" = test,\n    };\n    country = US;\n    disabled = 0;\n    email = \"[email protected]\";\n    \"email_verified\" = 1;\n    \"is_paired\" = 0;\n    };\n}"

It is similar to NSDictionary when it is printed as description to the console. Especially

  • some strings are in quotes, some are not. See country = US;\n
  • they use k-v notation with =. E.g. key = value
  • they use delimiter ;

Unfortunately I do not have the original object that created the string. I have only the string itself.

My goal is to transform it to a valid JSON string representation, or alternatively back to a NSDictionary. Should be done in Swift 5. I failed so far in doing so, does anyone has sample code that would help?


Solution

  • The description of an NSDictionary produces an “Old-Style ASCII Property List”, and PropertyListSerialization can be used to convert that back to an object.

    Note that the format is ambiguous. As an example, 1234 can be both a number or a string consisting of decimal digits only. So there is no guarantee to get the exact result back.

    Example:

    let desc = "{\n    \"account_no\" = \"5675672343244\";\n    \"account_kind\" =     {\n        \".tag\" = test;\n    };\n    country = US;\n    disabled = 0;\n    email = \"[email protected]\";\n    \"email_verified\" = 1;\n    \"is_paired\" = 0;\n}"
    
    do {
        let data = Data(desc.utf8)
        if let dict = try PropertyListSerialization.propertyList(from: data, format: nil) as? NSDictionary {
            let json = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
            print(String(data: json, encoding: .utf8)!)
        } else {
            print("not a dictionary")
        }
    } catch {
        print("not a valid property list:", error)
    }
    

    Output:

    {
      "country" : "US",
      "email_verified" : "1",
      "is_paired" : "0",
      "account_no" : "5675672343244",
      "email" : "[email protected]",
      "disabled" : "0",
      "account_kind" : {
        ".tag" : "test"
      }
    }
    

    (I had to “fix” the description string to make it a valid property list: "test" was followed by a comma instead of a semicolon, and there was an unbalanced } at the end of the string.)