Я пишу Swift для iOS 11, и в некотором контексте (описанном в части 2) я получаю переменную типа String. Тем не менее, при проверке переменной в отладчике XCode тип отображается как _PFEncodedString (который я читал в другом месте, является внутренним подклассом String). По какой-то причине (описанной ниже, но не имеющей прямого отношения к первой части моего вопроса) я хочу преобразовать переменную _PFEncodedString в обычную строковую переменную. Я нашел единственный способ сделать это следующим образом:
var attributeName : String
// ... attributeName is assigned a value and ends up being _PFEncodedString
let data = attributeName.data(using: String.Encoding.utf8)!
let plainName = String(data: data, encoding: String.Encoding.utf8)! // this is type String not _PFEncodedString
Первая часть моего вопроса : Безопасно ли это преобразование или есть более простой или лучший способ сделать это?
Часть 2. Во второй части моего вопроса я сначала опишу контекст, в котором вышеизложенное становится проблемой. Я использую Core Data и хочу экспортировать имена атрибутов (и значения) в JSON. Используя отражение, я могу найти имена сущностей Core Data и найти имена атрибутов, которые должны быть экспортированы в JSON. Проблема в том, что когда я использую JSONEncoder с этими данными, сгенерированный JSON содержит китайские символы, а имена атрибутов модели Core Data - нет. Я обнаружил, что JSONEncoder производит частично китайский вывод, когда Strings в экспортируемом объекте имеет тип _PFEncodedString, но отлично работает при обработке «простых» типов String. Поэтому первая часть моих вопросов.
Вот код, иллюстрирующий проблему, сведенный к минимуму. QPTVideo является подклассом NSManagedObject с двумя атрибутами: «qaUUID» и «thumbnailData».
// First define a struct to be used with JSONEncoder
struct AttributeForJSON : Codable {
var name : String
}
let entityDescription = QPTVideo.entity()
let attributes = entityDescription.attributesByName // this is an array of (key: String, value: NSAttributeDescription).
var allAttributes : [AttributeForJSON] = [] // this will be an array of all the attribute names for export to JSON.
for attribute in attributes {
let attributeName = attribute.key // NOTE: debugger shows this as: attributeName String class name = _PFEncodedString
let aj = AttributeForJSON(name: attributeName)
print(aj.name) // this works just fine, printing “qaUUID” or “thumbnailData”
allAttributes.append(aj) // when exported, the attribute names look nothing like they should, containing Chinese characters.
// now use the work-around from first part of my question:
let data = attributeName.data(using: String.Encoding.utf8)!
let plainName = String(data: data, encoding: String.Encoding.utf8)! // NOTE: debugger shows this as: plainName String "thumbnailData"
let ajplain = AttributeForJSON(name: plainName)
allAttributes.append(ajplain) // when exported, the attribute names are correct.
}
// the rest is just use of JSONEncoder to generate the JSON
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
do {
let data = try encoder.encode(allAttributes)
try data.write(to: URL(fileURLWithPath: “/Users/someone/so.json"), options: Data.WritingOptions.atomic)
} catch {
print(error.localizedDescription)
}
Экспортированный JSON выглядит следующим образом (где я ожидал, что оба первых значения name
будут иметь значение «qaUUID», а следующие два - «thumbnailData»):
[
{
"name" : "慱啕䑉\u0000戨্"
},
{
"name" : "qaUUID"
},
{
"name" : "桴浵湢楡䑬瑡a\u0000戨্\u0001\u0000\u0000"
},
{
"name" : "thumbnailData"
}
]
Итак, мой здесь вопрос : Почему я получаю китайские иероглифы? Что я делаю неправильно в том, как я использую API-интерфейс отражения основных данных и / или JSONEncoder? Как мне сделать это, не прибегая к обходным путям из первой части моего вопроса?