Лучший способ удалить недопустимые символы json из json-подобной строки перед демаршалированием

Чтобы дать некоторый фон, я читаю журналы устройств с устройств Android и ios, используя adb logcat и idevicesyslog. Конкретные журналы, которые мне нужны, — это словари swift/c#/java/etc, преобразованные в строки через adb logcat/idevicesyslog. Я надеюсь взять эти журналы, содержащие строки, подобные JSON, и преобразовать их в действительный JSON. Это работает по большей части без проблем.

Однако иногда эти журналы/строковые выходные данные содержат такие символы, как (\134, \M, \t и т. д.), которые вызывают проблемы при распаковке в JSON. Я распаковываю их в JSON, чтобы отправить в другое место.

Например, необработанный журнал устройства может иметь что-то вроде следующего: {"foo":"bar","foo":"bar\134/\134/bar\134/bar\134/bar"} {"foo": "бар","foo":"бар\М/\134/бар\134/бар\М/бар"}

Это приводит к таким ошибкам, как «паника: недопустимый символ 'M' в escape-коде строки» при попытке демаршалировать

Большинство журналов не содержат этих символов, так что это не проблема. Однако некоторые крайние случаи содержат их, и это создает проблемы.

Есть ли правильное название для этих типов персонажей? (escape-символы С#?) Есть ли пакет golang, который может удалить их из строки? В настоящее время я просто удаляю те, с которыми сталкиваюсь, если они появляются в строке, но мне кажется, что есть лучший способ сделать это. Добавление тех, с которыми я сталкиваюсь, в список удаляемых символов не является хорошей практикой.

Подвести итоги,

Журнал idevicesyslog дает мне такую ​​строку: {"foo":"bar","foo":"bar\134/\134/bar\134/bar\134/bar"}

Это не может быть unmarshalled.

Журнал idevicesyslog дает мне такую ​​строку: {"foo":"bar","foo":"bar bar bar bar"}

Это может быть неупорядочено.

Текущее решение: добавить новые, с которыми я сталкиваюсь, в список и удалить их перед демаршалингом.

Обнадеживающее решение: автоматически обнаруживать и удалять


person Steve    schedule 19.01.2019    source источник
comment
Похоже, текст содержит недопустимые escape-последовательности JSON. Это отличается от содержания текста, отличного от utf8. Непонятно, что вы хотите удалить. Достаточно ли удалить обратную косую черту, обратную косую черту и следующий символ или что-то еще? Приведите примеры исходной строки и строки, в которую вы хотите ее преобразовать. Чтобы избежать путаницы, опишите формат строк. Например, печатаются ли они с помощью fmt.Sprintf(%s, s), fmt.Sprintf(%q, s) или чего-то еще?   -  person Cerise Limón    schedule 20.01.2019
comment
Я думаю, что это эти символы (из списка escape-символов С#), которые являются частью строки, полученной на выходе idevicesyslog (github.com/libimobiledevice/libimobiledevice/blob/master/docs/) Я не контролирую печать строки, а скорее отфильтровываю нужные мне журналы из idevicesyslog /adb logcat. Примеры, которые я видел: \047 одинарная кавычка \134 обратная косая черта \140 серьезный ударение   -  person Steve    schedule 20.01.2019
comment
поскольку libimobiledevice написан на c, они используют fprintf или fflush, я думаю   -  person Steve    schedule 20.01.2019
comment
В случае \047 содержит ли строка байты 92, 48, 52, 55? Ваша цель заменить эти четыре байта одним байтом 47 (одинарная кавычка)?   -  person Cerise Limón    schedule 20.01.2019
comment
Моя цель — заменить их символами, которые не вызывают ошибок десортировки. Так что я думаю, заменив их все пустой строкой. Однако я не был уверен, что для этого есть встроенный пакет. В противном случае мне придется составить список и выполнить поиск и замену в каждом журнале, содержащем эти символы. Если я сам составлю список, то это может привести к ошибкам, так как я не знаю всего, что существует.   -  person Steve    schedule 20.01.2019
comment
Проблема заключается в недопустимых escape-последовательностях, а не в недопустимых символах. Похоже, ваша цель состоит в том, чтобы преобразовать экранирование из того, что произвело этот текст, в допустимые escape-последовательности JSON. В тесте, показанном в вопросе, нет недопустимых символов.   -  person Cerise Limón    schedule 20.01.2019
comment
Да, это кажется правильным. Ошибка, которую я получаю, - это паника: недопустимый символ '\ 134' в коде escape-последовательности строки при демаршалинге в json. Я конвертирую строку в [] байт и демаршалирую: err = json.Unmarshal([]byte(s), &metadataMap)   -  person Steve    schedule 20.01.2019
comment
Если бы все escape-последовательности были похожи на \nnn (т.е. восьмеричные escape-последовательности в стиле C), я бы предложил использовать регулярное выражение для замены обратной косой черты, за которой следуют три цифры, но наличие \M означает, что это не будет работать для всех строк, и на самом деле это не стандартный побег, с которым я сталкивался, поэтому вам может потребоваться просто вести список побегов, которые нужно заменить.   -  person lmars    schedule 20.01.2019
comment
Да, этот разговор с вами обоими был полезен, и я думаю, что то, чего я боялся (например, отслеживание и замена каждого), мне нужно будет сделать. Либо так, либо перепишите эти регистраторы устройств с открытым исходным кодом на ходу. В настоящее время используется что-то вроде этого (когда \134 был единственным, вызывающим проблемы): func replaceSpChar(s string) string { var jsonStr = s specialChar := strings.Contains(jsonStr, \134) if specialChar { jsonStr = strings.Replace(jsonStr, \134, "", -1) } return jsonStr } просто нужно создать список всех.   -  person Steve    schedule 20.01.2019
comment
Я думаю, может быть, просто заменить все \ на \\ также может быть реалистично: strings.Replace(str, "\\", "\\\\", -1)   -  person Steve    schedule 20.01.2019


Ответы (1)


Используйте регулярное выражение, чтобы заменить недопустимые восьмеричные escape-последовательности пробелом:

var octalEscapePat = regexp.MustCompile(`\\[0-7]{3}`)

func fix(src string) string {
    return octalEscapePat.ReplaceAllString(src, " ")
}

Вы также можете проанализировать восьмеричное значение и преобразовать его в допустимую управляющую последовательность JSON:

func fix(src string) string {
    return octalEscapePat.ReplaceAllStringFunc(src, func(s string) string {
        // Parse octal value
        n, _ := strconv.ParseInt(s[1:], 8, 0)
        // Convert to string and marshal to JSON to handle any escaping
        b, _ := json.Marshal(string(n))
        // return string with surrounding quotes removed
        return string(b[1 : len(b)-1])
    })
}

\M можно обрабатывать аналогичным образом.

https://play.golang.org/p/-gtxrvnBSrx

person Cerise Limón    schedule 20.01.2019
comment
Ницца. Спасибо! Одна вещь, которую я заметил, заключается в том, что большинство этих восьмеричных экранов происходят с данными URL. например https:\134/\134/foo.net\134/i\134/bar\134/foo\134/bar\134/m3u8\134/300\134/master.m3u8 - person Steve; 20.01.2019
comment
@Steve По какой-то причине исходное приложение избегает косой черты. Это не нужно. Используйте регулярное выражение `\\134/` и замените на "/", чтобы исправить это. - person Cerise Limón; 20.01.2019
comment
Здесь удалось найти проблему: github.com/flutter/flutter/issues/10218 Возможное решение (хотя и в дротике): github.com/flutter/flutter/pull/14075/ файлы - person Steve; 22.01.2019
comment
Код Dart имеет хорошую документацию по формату, с которым вы имеете дело, и его должно быть легко перевести на Go. - person Cerise Limón; 22.01.2019