我正在创建一个JSON结构,我最终需要将其保存到文件中,但是我遇到嵌入式换行符问题。
我首先创建一个字典:
changes = {
"20161101": "Added logging",
"20161027": "Fixed scrolling bug",
"20161024": "Added summary functionality"
}
然后将其转换为单个换行符分隔的字符串:
changes_str = '\n'.join([ "{0} - {1}".format(x, y) for x, y in changes.items() ])
print changes_str
'20161101 - Added logging\n20161027 - Fixed scrolling bug\n20161024 - Added summary functionality'
到目前为止,这么好。现在我将它添加到字符串中(实际上它将来自文本模板):
changes_str_json_str = '{ "version": 1.1, "changes": "' + changes_str + '" }'
print changes_str_json_str
'{ "version": 1.1, "changes": 20161101 - Added logging\n20161027 - Fixed scrolling bug\n20161024 - Added summary functionality }'
但是当我使用load来创建/编码JSON对象时,我遇到了问题:
json_obj = json.loads(changes_str_json_str)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/python2.7/json/__init__.py", line 339, in loads
return _default_decoder.decode(s)
File "/opt/python2.7/json/decoder.py", line 364, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/opt/python2.7/json/decoder.py", line 380, in raw_decode
obj, end = self.scan_once(s, idx)
ValueError: Invalid control character at: line 1 column 55 (char 54)
将换行符更改为另一个字符确实可以清楚地解决问题所在的问题,但是,我确实需要将该字符作为换行符,因为最终文件中的数据需要格式化为这个(文件传递给另一个我无法控制的系统。另外,据我所知,换行是JSON字符串中支持的字符。
这里究竟出现了什么问题以及如何解决这个问题?
答案 0 :(得分:1)
在JSON中,您需要正确转义包括\n
在内的控制字符。以下是目前正在发生的事情的例子:
>>> import json
>>> json.loads('"foo\nbar"')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\python35\lib\json\__init__.py", line 319, in loads
return _default_decoder.decode(s)
File "C:\python35\lib\json\decoder.py", line 339, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "C:\python35\lib\json\decoder.py", line 355, in raw_decode
obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Invalid control character at: line 1 column 5 (char 4)
如果使用反斜杠正确转义换行符,它将按预期工作:
>>> json.loads('"foo\\nbar"')
'foo\nbar'
因此,您可以通过执行以下操作来修复代码:
changes_str = '\\n'.join([ "{0} - {1}".format(x, y) for x, y in changes.items() ])
更好的选择是首先构造您想要输出的对象,然后使用dumps
,这样您根本不必担心转义:
obj = {
'version': 1.1,
'changes': changes_str
}
changes_str_json_str = json.dumps(obj)
答案 1 :(得分:0)
将其转换为单个换行符分隔的字符串:
/**
* Checks given IP against array of masks like 123.123.123.123, 123.123.*.101, 123.123., 123.123.1*.*
*
* @param $ip
* @param $masks
* @return bool
*/
public static function checkIp($ip, $masks)
{
if (in_array($ip, $masks)) {
return true; // Simple match
} else {
foreach ($masks as $mask) {
if (substr($mask, -1) == '.' AND substr($ip, 0, strlen($mask)) == $mask) {
return true; // Case for 123.123. mask
}
if (strpos($mask, '*') === false) {
continue; // No simple matching and no wildcard in the mask, leaves no chance to match
}
// Breaking into triads
$maskParts = explode('.', $mask);
$ipParts = explode('.', $ip);
foreach ($maskParts as $key => $maskPart) {
if ($maskPart == '*') {
continue; // This triad is matching, continue with next triad
} elseif (strpos($maskPart, '*') !== false) {
// Case like 1*, 1*2, *1
// Let's use regexp for this
$regExp = str_replace('*', '\d{0,3}', $maskPart);
if (preg_match('/^' . $regExp . '$/', $ipParts[$key])) {
continue; // Matching, go to check next triad
} else {
continue 2; // Not matching, Go to check next mask
}
} else {
if ($maskPart != $ipParts[$key]) {
continue 2; // If triad has no wildcard and not matching, check next mask
}
// otherwise just continue
}
}
// We checked all triads and all matched, hence this mask is matching
return true;
}
// We went through all masks and none has matched.
return false;
}
}
在dict python中加载字符串JSON:
import json
changes_str = json.dumps(changes)