Преобразуйте MFC CString в целое число

Проблема в том, что соответствие Codable в настоящее время может правильно обрабатывать только клавиши String и Int. Для словаря с любым другим типом Key (где этот Key равен Encodable / Decodable), он кодируется и декодируется с помощью контейнера без ключа (массив JSON) со значениями чередующегося ключа. [1 134]

Поэтому при попытке декодировать JSON:

{"dictionary": {"enumValue": "someString"}}

в AStruct значение ключа "dictionary", как ожидается, будет массивом.

Таким образом,

let jsonDict = ["dictionary": ["enumValue", "someString"]]

будет работать, давая JSON:

{"dictionary": ["enumValue", "someString"]}

, который затем будет декодирован в:

AStruct(dictionary: [AnEnum.enumValue: "someString"])

Однако, на самом деле я думаю, что Codable соответствие [1120] должно быть способным правильно работать с любым CodingKey соответствующим типом как его Key (который может быть AnEnum) - так как он может просто кодировать и с этим ключом декодировать в контейнер с ключами (не стесняйтесь подать запрос об ошибке )

До реализации (если это вообще возможно), мы всегда могли создать тип оболочки, чтобы сделать это:

struct CodableDictionary : Codable where Key : CodingKey {

    let decoded: [Key: Value]

    init(_ decoded: [Key: Value]) {
        self.decoded = decoded
    }

    init(from decoder: Decoder) throws {

        let container = try decoder.container(keyedBy: Key.self)

        decoded = Dictionary(uniqueKeysWithValues:
            try container.allKeys.lazy.map {
                (key: [114], value: try container.decode(Value.self, forKey: [114]))
            }
        )
    }

    func encode(to encoder: Encoder) throws {

        var container = encoder.container(keyedBy: Key.self)

        for (key, value) in decoded {
            try container.encode(value, forKey: key)
        }
    }
}

, а затем реализовать так:

enum AnEnum : String, CodingKey {
    case enumValue
}

struct AStruct: Codable {

    let dictionary: [AnEnum: String]

    private enum CodingKeys : CodingKey {
        case dictionary
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        dictionary = try container.decode(CodableDictionary.self, forKey: .dictionary).decoded
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(CodableDictionary(dictionary), forKey: .dictionary)
    }
}

(или просто иметь свойство dictionary типа CodableDictionary и использовать автоматически сгенерированное соответствие Codable - тогда просто поговорим в терминах dictionary.decoded)

Теперь мы можем декодировать вложенный объект JSON, как и ожидалось:

let data = """
{"dictionary": {"enumValue": "someString"}}
""".data(using: .utf8)!

let decoder = JSONDecoder()
do {
    let result = try decoder.decode(AStruct.self, from: data)
    print(result)
} catch {
    print(error)
}

// AStruct(dictionary: [AnEnum.enumValue: "someString"])

Несмотря на все сказанное, можно утверждать, что все, чего вы достигнете с помощью словаря с enum в качестве ключа, это просто struct с дополнительными свойствами (и если вы ожидайте, что данное значение всегда будет там, сделайте его необязательным).

Поэтому вы можете просто захотеть, чтобы ваша модель выглядела следующим образом:

struct BStruct : Codable {
    var enumValue: String?
}

struct AStruct: Codable {

    private enum CodingKeys : String, CodingKey {
        case bStruct = "dictionary"
    }

    let bStruct: BStruct
}

Что бы отлично работать с вашим текущим JSON:

let data = """
{"dictionary": {"enumValue": "someString"}}
""".data(using: .utf8)!

let decoder = JSONDecoder()
do {
    let result = try decoder.decode(AStruct.self, from: data)
    print(result)
} catch {
    print(error)
}

// AStruct(bStruct: BStruct(enumValue: Optional("someString")))

41
задан Ajay 27 May 2016 в 12:07
поделиться

4 ответа

Простейший подход - использовать функцию atoi () , найденную в stdlib.h :

CString s = "123";
int x = atoi( s );

Однако это плохо работает с случай, когда строка не содержит действительного целого числа, и в этом случае вам следует изучить функцию strtol () :

CString s = "12zzz";    // bad integer
char * p;
int x = strtol ( s, & p, 10 );
if ( * p != 0 ) {
   // s does not contain an integer
}
36
ответ дан 27 November 2019 в 00:15
поделиться
CString s;
int i;
i = _wtoi(s); // if you use wide charater formats
i = _atoi(s); // otherwise
16
ответ дан 27 November 2019 в 00:15
поделиться

вы также можете использовать старый добрый sscanf.

CString s;
int i;
int j = _stscanf(s, _T("%d"), &i);
if (j != 1)
{
   // tranfer didn't work
}
8
ответ дан 27 November 2019 в 00:15
поделиться

Если вы используете TCHAR.H рутину (неявно или явно), убедитесь, что вы используете _ttoi() функцию, чтобы она компилировалась как для Unicode, так и для ANSI компиляции.

Подробнее: https://msdn.microsoft.com/en-us/library/yd5xkb5c.aspx

39
ответ дан 27 November 2019 в 00:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: