JsonNode 中的 asText() 和 toString() 有啥区别?
Posted
技术标签:
【中文标题】JsonNode 中的 asText() 和 toString() 有啥区别?【英文标题】:What is the difference between asText() and toString() in JsonNode?JsonNode 中的 asText() 和 toString() 有什么区别? 【发布时间】:2018-07-17 05:28:05 【问题描述】:所以我试图在 POST 之后验证一些有效负载。
有效负载 (JSON) 如下所示:
"value":"\"<html><body><a href='http://www.example.com'>Hi there!</a></body></html>\""
然后我尝试将上面的内容转换为 JsonNode 并提取“value”的值。但是,asText()
和 toString()
这两种方法返回不同的字符串值。
这两种方法的工作方式有何不同?
给定字符串"\"<html><body><a href='http://www.example.com'>Hi there!</a></body></html>\""
toString 返回"<html><body><a href='http://www.example.com'>Hi there!</a></body></html>"
asText() 返回<html><body><a href='http://www.example.com'>Hi there!</a></body></html>
【问题讨论】:
第一个序列化为JSON,第二个不是。 @shmosel,好吧,这是有道理的。但是asText()方法序列化成什么结果呢? 没有序列化。它只是一个字符串值。 【参考方案1】:我要补充的一点是,如果字符串很长,对我来说,只使用.toString()
,因为其他两个(.asText()
和.textValue()
)将分别返回空字符串和 null。
【讨论】:
【参考方案2】:TL;DR:
只有master分支有接受答案的行为;在此之前的版本,如 Jackson 2.9,toString()
不仅仅是“在字符串周围添加引号”。
如果你想检查一些包含键值对(一个JSON对象)的JsonNode的文本表示,你必须使用toString()
; asText()
会得到你""
,因为它不是ValueNode
。并且,在此过程中,Unicode (\uxxxx
) 将被转换为实际字符。
详细说明:
我用我拥有的库进行了测试,然后我发现我不能同意接受的答案。我的是2.9。
就我而言,toString()
不仅仅是添加引号。它还将保留字符串内容中的转义字符,至少从版本 2.0 到 2.9。
查看来源here(注意网址中的版本,可以在页面中选择版本,直到2.10)
2.0:
/**
* Different from other values, Strings need quoting
*/
@Override
public String toString()
int len = _value.length();
len = len + 2 + (len >> 4);
StringBuilder sb = new StringBuilder(len);
appendQuoted(sb, _value);
return sb.toString();
protected static void appendQuoted(StringBuilder sb, String content)
sb.append('"');
CharTypes.appendQuoted(sb, content);
sb.append('"');
fasterxml.jackson.core.io.CharTypes.appendQuoted()
将保留一些转义字符。在here查看它的源代码。(注意代码来自2.0分支,不是master)
public static void appendQuoted(StringBuilder sb, String content)
final int[] escCodes = sOutputEscapes128;
int escLen = escCodes.length;
for (int i = 0, len = content.length(); i < len; ++i)
char c = content.charAt(i);
if (c >= escLen || escCodes[c] == 0)
sb.append(c);
continue;
sb.append('\\');
int escCode = escCodes[c];
if (escCode < 0) // generic quoting (hex value)
// We know that it has to fit in just 2 hex chars
sb.append('u');
sb.append('0');
sb.append('0');
int value = -(escCode + 1);
sb.append(HEX_CHARS[value >> 4]);
sb.append(HEX_CHARS[value & 0xF]);
else // "named", i.e. prepend with slash
sb.append((char) escCode);
但是,正如接受的答案所说,现在master
分支似乎将此行为简化为“仅添加引号”。这可以在this page 中看到。实际上,这个提交的标题是
移除对 CharTypes.appendQuoted() 的依赖;将
JsonNode.toString()
的引号更改为单引号,以防止用于 JSON 生成
但同样,我使用的是 2.9,而CharTypes.appendQuoted()
仍在使用。因此,通常情况下,如果您不使用 master 分支,toString()
将保留转义字符。
例子:
JsonNode node = new TextNode("\"en_us\":\"54\",\"es_es\":\"54\"");
node.asText(); // -> "en_us":"54","es_es":"54", no quotations, no escaping
node.toString(); // -> "\"en_us\":\"54\",\"es_es\":\"54\"", add quotations, perserves escaping.
因此,注意 lib 版本并不总是“大师”!
对于带有对象的JsonNode
的toString()
,请检查:(Jackson data-bind 2.9)
@Test
public void testToString()
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.createObjectNode();
((ObjectNode) node).put("es_es", "Categor\u00eda ra\u00edz/CATEGORY_OMS_DATA/");
System.out.println((node.toString())); // "es_es":"Categoría raíz/CATEGORY_OMS_DATA/", note: not quotations around!! not like TextNode!
System.out.println(node.asText()); // empty
【讨论】:
【参考方案3】:asText ()
它是来自JsonNode
的抽象方法,在TextNode
中被覆盖。而且,根据它的实现,它应该在没有任何操作的情况下返回值。
@Override
public String asText()
return _value;
toString ()
它被 Object
覆盖。因此,它是对象的文本表示。所以,toString
实际上会返回给定对象的完整文本形式。而且,根据它在TextNode
中的实现。它将引号(在开头和结尾)附加到您的值。
/**
* Different from other values, Strings need quoting
*/
@Override
public String toString()
int len = _value.length();
len = len + 2 + (len >> 4);
return new StringBuilder(len)
// 09-Dec-2017, tatu: Use apostrophes on purpose to prevent use as JSON producer:
.append('\'')
.append(_value)
.append('\'')
.toString();
而且,当您打印它们时,您也可以看到相同的差异。
【讨论】:
我认为这是有道理的。所以当payload被序列化为JSON时,实际值变成了html字符串,asText()按原样返回,toString()会在html字符串两边加上引号。我理解正确吗? @JackZhang 是的,这正是我所说的。【参考方案4】:asText() 和 toString() 的区别
公共抽象字符串asText()
如果节点是值节点(方法 isValueNode() 返回 true),则返回容器值的有效字符串表示的方法,否则为空字符串。
public String readNameNode()
JsonNode nameNode=rootNode.path("name");
String name=nameNode.asText();
logger.info("\n----------------------------\nEmployee Name: "+name+"\n");
return name;
公共抽象字符串toString()
注意:标记为抽象以确保所有实现类都正确定义它。
覆盖: 类中的 toString
public String readNameNode()
JsonNode nameNode=rootNode.path("name");
String name=nameNode.toString();
logger.info("\n----------------------------\nEmployee Name: "+name+"\n");
return name;
希望你理解 asText 方法和 toString 方法之间的确切区别
【讨论】:
以上是关于JsonNode 中的 asText() 和 toString() 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章
Jackson 中的 ObjectNode 和 JsonNode 有啥区别?
如何检查 JsonNode 是 Java 中的单个元素还是数组?