JsonNode中的asText()和toString()有什么区别?

时间:2018-02-07 02:34:08

标签: java json string

所以我试图在POST后验证一些有效负载。

有效负载(JSON)如下所示:

{"value":"\"<html><body><a href='http://www.example.com'>Hi there!</a></body></html>\""}

然后我尝试将上面的内容转换为JsonNode并提取&#34; &#34;的值。但是,这两种方法asText()&amp; 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>

4 个答案:

答案 0 :(得分:6)

<强> 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();
}

而且,打印时也可以看到相同的区别。

答案 1 :(得分:0)

asText()和toString()

之间的区别

public abstract String asText()

如果节点是值节点(方法isValueNode()返回true),则返回容器值的有效String表示的方法,否则为空String。

public String readNameNode()
        {
            JsonNode nameNode=rootNode.path("name");
            String name=nameNode.asText();
            logger.info("\n----------------------------\nEmployee Name: "+name+"\n");
            return name;
        }

public abstract String 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方法之间的确切区别

答案 2 :(得分:0)

TL; DR:

  • 只有master分支具有接受的答案的行为;之前的版本(例如Jackson 2.9),toString()所做的不只是“在字符串周围添加引号”。

  • 如果要检查包含键值对(JSON对象)的某个JsonNode的文本表示形式,则必须使用toString(); asText()会让您"",因为它不是ValueNode。并且,在此过程中,Unicode(\uxxxx)将转换为实际字符。

详细信息:

我测试了拥有的lib,然后发现我不同意接受的答案。我的是2.9。

就我而言,toString()所做的不只是添加引号。至少从版本2.0到2.9,它还将保留字符串内容中的转义字符。

检查来源here(注意URL中的版本。您可以在页面中选择版本,直到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版本并不总是“主”!


对于带有对象的toString()中的JsonNode,请检查以下内容:(杰克逊数据绑定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 :(得分:0)

我要补充的一件事是,如果字符串很长,对我来说,只使用 .toString() 工作,因为其他两个(.asText().textValue())将返回空字符串和分别为null。