【问题标题】:Jackson read value as string杰克逊将值读取为字符串
【发布时间】:2013-02-05 08:19:15
【问题描述】:

我有一个值未知的对象,比如说

{
 "data": [
    {"a":...,
    "dont_know_what_else_is_here":....}
 ]
}

我只想将“数据”的值作为字符串存储到变量/数据库中。

我应该如何从流 API 中读取它?

【问题讨论】:

    标签: java json jackson


    【解决方案1】:

    前提是你已经将这个对象读入JsonNode,你可以这样做:

    String content = jsonNode.get("data").textValue();
    

    UPD:由于您使用的是流式解析器,this Jackson 用法示例可能会有所帮助。

    UPD:方法名称现在是 textValue() - docs

    【讨论】:

    • 感谢您的回答!这是来自流解析器,所以不幸的是它还没有读入 jsonNode。如果我可以将它读取到 json 节点,那么 toString 整个对象都可以工作。
    • @Edison 哦,我现在明白了。你检查过this 的例子吗?
    • 是的,我做到了,但数据数组中的结构未知。有什么想法吗?
    • 也编辑了这个问题。数据是一个包含混合对象的数组。
    • @joeybaruch asText() 会将任何非文本转换为字符串值,而 textValue() for 如果您确定它是一个字符串。
    【解决方案2】:

    当我们尝试从 JsonNode 获取字符串形式的数据时,我们通常使用 asText,但我们应该使用 textValue

    @987654321 @:将返回容器值的有效字符串表示的方法,如果节点是值节点(方法 isValueNode() 返回 true),否则为空字符串。

    textValue:用于访问的方法字符串值。不对非字符串值节点进行任何转换;对于非字符串值(isTextual() 返回 false 的值),将返回 null。对于 String 值,从不返回 null(但可能是空字符串)

    那么我们举个例子,

    JsonNode getJsonData(){
        ObjectMapper mapper = new ObjectMapper();
        ObjectNode node = mapper.createObjectNode(); 
        node.put("anyParameter",null);
        return node;
    }
    JsonNode node = getJsonData();
    json.get("anyParameter").asText() // this will give output as "null"
    json.get("").textValue() // this will give output as null
    

    【讨论】:

      【解决方案3】:

      您可以根据键值对获取地图中的数据。

      Map<String, Object> mp = mapper.readValue(new File("xyz.txt"),new TypeReference<Map<String, Object>>() {});
      

      现在从地图中获取值:

      mp.get("data");
      

      【讨论】:

      • 我正在使用流式解析器,所以我不想读取整个“数据”。
      • @dejavu 嗨,使用映射器从 URL 获取刺痛的最佳方法是什么?
      • 如何在java中将jsonNode转成string[]?
      【解决方案4】:

      假设您已经有一个 解析器 并且它指向 "data" 令牌(例如来自自定义反序列化器),您可以执行以下操作:

      ObjectMapper mapper = new ObjectMapper();
      JsonNode treeNode = mapper.readTree(parser);
      return treeNode.toString();
      

      这将为您提供包含 "data" 值的字符串。

      【讨论】:

        【解决方案5】:

        您可以为 JSON 结果设置一些实体类。

        String json = "your_json";
        ObjectMapper mapper = new ObjectMapper();
        Entity entity = mapper .readValue(json, Entity.class);
        // here you can do everything with entity as you wish
        
        // to write Entity value as String when you wish
        String text = mapper.writeValueAsString(object);
        // to write Entity child's value as String when you wish (let's data contain data part)
        String data = mapper.writeValueAsString(object.getData());
        

        【讨论】:

          【解决方案6】:

          假设您有一个名为 User(Taken from this) 的 POJO java 类

          public class User {
          public enum Gender { MALE, FEMALE };
          
          public class Name {
              private String _first, _last;
          
              public String getFirst() { return _first; }
              public String getLast() { return _last; }
          
              public void setFirst(String s) { _first = s; }
              public void setLast(String s) { _last = s; }
          }
          
          private Gender _gender;
          private Name _name;
          private boolean _isVerified;
          private byte[] _userImage;
          
          public Name getName() { return _name; }
          public boolean isVerified() { return _isVerified; }
          public Gender getGender() { return _gender; }
          public byte[] getUserImage() { return _userImage; }
          
          public void setName(Name n) { _name = n; }
          public void setVerified(boolean b) { _isVerified = b; }
          public void setGender(Gender g) { _gender = g; }
          public void setUserImage(byte[] b) { _userImage = b; }
          

          }

          所以现在你有来自任何地方的 JSON 字符串,比如 web socket 或其他地方。作为一个例子假设这是你得到的字符串

          String json = "{\n" +
                      "  \"name\" : { \"first\" : \"Joe\", \"last\" : \"Sixpack\" },\n" +
                      "  \"gender\" : \"MALE\",\n" +
                      "  \"verified\" : false,\n" +
                      "  \"userImage\" : \"Rm9vYmFyIQ==\"\n" +
                      "}";
          

          现在您只需使用这段代码就可以将这个 JSON 字符串转换为 POJO 对象。

          ObjectMapper mapper = new ObjectMapper();
          User user = mapper .readValue(json, User.class);
          

          【讨论】:

            【解决方案7】:

            我假设您只想使用 Streaming API 从输入中读取子树——但最后,您需要将整个子树作为一件事存储在数据库(或变量)中。

            所以你可能想要使用的是JsonParser.readValueAs(MyType.class)——这将调用ObjectMapper(为了让它工作,解析器必须通过JsonFactoryObjectMapper访问;或者你需要调用@ 987654325@)。

            如果内容随意,可以读成MapJsonNode

            Map<String,Object> map = parser.readValueAs(Map.class);
            // or
            JsonNode root = parser.readValueAsTree();
            

            只要JsonParser 指向您要数据绑定的 JSON 对象的 START_ELEMENT。

            【讨论】:

              【解决方案8】:

              如果在createParser(data) 中使用String data,我使用此方法通过流式API 收集字符串内容:

              if ("data".equals(fieldname))
                   String strData = getValueAsString(jp);
              

                  private static String getValueAsString(JsonParser jp)
                      throws com.fasterxml.jackson.core.JsonParseException, IOException {
                  JsonToken token = jp.getCurrentToken();
                  int counter = 0;
              
                  long startIndex = jp.getCurrentLocation().getCharOffset();
                  long endIndex = 0;
              
                  if (token == JsonToken.START_OBJECT) {
                      // JsonLocation location = jp.getCurrentLocation();
                      // startIndex = location.getCharOffset();
                      // System.out.println(",location=" + new Gson().toJson(location) +
                      // ", start=" + startIndex);
              
                      counter++;
                      while (counter > 0) {
                          token = jp.nextToken();
                          if (token == JsonToken.START_OBJECT)
                              counter++;
                          if (token == JsonToken.END_OBJECT) {
                              counter--;
                              endIndex = jp.getCurrentLocation().getCharOffset();
                          }
                      }
              
                      return data.substring((int) startIndex - 1, (int) endIndex);
              
                  } else if (token == JsonToken.START_ARRAY) {
                      counter++;
                      while (counter > 0) {
                          token = jp.nextToken();
                          if (token == JsonToken.START_ARRAY)
                              counter++;
                          if (token == JsonToken.END_ARRAY) {
                              counter--;
                              endIndex = jp.getCurrentLocation().getCharOffset();
                          }
                      }
                      return data.substring((int) startIndex - 1, (int) endIndex);
              
                  } else {
                      return jp.getText();
                  }
              }
              

              当数据源为字符串时有效。对于文件等无字符串源,使用JsonLocation.getByteOffset() 而不是JsonLocation.getCharOffset()

              【讨论】:

                【解决方案9】:

                通过阅读教程页面终于找到了解决方案。

                这里只是给别人指点一下:

                1. 在创建解析器时切换到使用 MappingJSONFactory:

                      HttpResponse response = client.execute(request);
                      JsonFactory jfactory = new MappingJsonFactory();
                      JsonParser parser=jfactory.createJsonParser(response.getEntity().getContent());
                  
                2. 那你就可以了

                      parser.readValueAsTree().toString();
                  

                或根据需要解析它。

                【讨论】:

                • 上次我检查过,一些 toString 方法仅用于调试,不能保证生成代表其内容的有效 JSON。
                • 很高兴知道。它在一个非常复杂的对象上对我有用。是时候仔细检查了...
                • 幸运的是,“org.codehaus.jackson.map.MappingJsonFactory”确实正确实现了 toString。 :) @ProgrammerBruce
                • 现在。但是我没有在 JavaDocs 中看到它可以保证在未来的版本中继续工作。
                • @ProgrammerBruce 你是对的,JsonNode.toString() 不是进行转换的正确方法——相反,应该使用ObjectMapper.writeValueAsString(node)
                猜你喜欢
                • 2019-08-19
                • 2015-07-28
                • 1970-01-01
                • 2017-10-03
                • 1970-01-01
                • 2017-09-22
                • 2021-04-01
                • 1970-01-01
                相关资源
                最近更新 更多