【问题标题】:JSON String to Java StringJSON字符串到Java字符串
【发布时间】:2017-11-28 04:28:19
【问题描述】:

我有这些 JSON 字符串:

{
    "Results": {
        "output1": {
            "type": "table",
            "value": {
                "ColumnNames": ["userId", "documentId", "Scored Labels", "Scored Probabilities"],
                "ColumnTypes": ["String", "String", "Boolean", "Double"],
                "Values": [["100213199594809000000", "1Ktol-SWvAh8pnHG2O7HdPrfbEVZWX3Vf2YIPYXA_8gI", "False", "0.375048756599426"], ["103097844766994000000", "1jYsTPJH8gaIiATix9x34Ekcj31ifJMkPNb0RmxnuGxs", "True", "0.753859758377075"]]
            }
        }
    }
}

我只想拥有ColumnNamesValues。我已经尝试过这样的事情:

Map<String,Object> map = mapper.readValue(filename, Map.class);
String CN = (String) map.get("ColumnNames");

然后我收到以下错误:

Exception in thread "main" org.codehaus.jackson.JsonParseException: Unexpected character ('A' (code 65)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')
 at [Source: java.io.StringReader@64232b15; line: 1, column: 2]`

我只用过几次 JSON。有人可以帮我吗?

对我来说最好的情况是这样的,我在另一种情况下做过:

String uId = (String) attr.get("userId");

有可能吗?

所以现在我已经这样做了:

我是这样尝试的:

public class ClientPOJO {

    private String userId;
    private String documentId;


    public String getuserId() {
        return userId;
    }

    public void setuserId(String userId) {
        this.userId = userId;
    }

    public String getdocumentId() {
        return documentId;
    }

    public void setdocumentId(String documentId) {
        this.documentId = documentId;
    }

}

然后:

ObjectMapper mapper = new ObjectMapper();
                    ClientPOJO clientes= mapper.readValue(filename, ClientPOJO.class);

String uid = clientes.getuserId();

但是现在当我制作一个 Prtinout 时,我会得到和以前一样的错误:

    Exception in thread "main" org.codehaus.jackson.JsonParseException: Unexpected character ('A' (code 65)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')
 at [Source: java.io.StringReader@7a6eb29d; line: 1, column: 2]

【问题讨论】:

  • 必须使用jackson还是可以使用其他JSON库?
  • 其他库也适合我。要点是,我必须以单独的形式获取 userId、documentID 和评分标签。我需要这个,因为我稍后再发送。
  • 在这种情况下,请查看其他问题,例如 stackoverflow.com/questions/11874919/…。您需要做的就是获取由“Results”键持有的 json 对象,然后从该对象获取由“value”键持有的对象。从那里获取“ColumnNames”和“Values”的 json 数组。
  • 尝试转换为 java 模型对象(PO​​JO),以便访问属性。
  • 当我在 Pshemo 的链接中尝试它时,我得到了错误:方法 getJSONObject(int) is undefined for the type JSONArray

标签: java json string jackson


【解决方案1】:

Java-将JSON字符串转换成字符串/整数/对象

String jsonString = "{"username":"Gajender"}";
org.json.JSONObject jsonObj =new JSONObject(jsonString);
String name = (String) jsonObj.get("username").toString();

【讨论】:

    【解决方案2】:

    以下示例说明了解决问题的通用方法(基于 Jackson 库)。您可能希望增强解决方案以满足您的所有要求。

    内嵌评论。

    package com.stackoverflow;
    
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    
    import org.junit.Test;
    
    import com.fasterxml.jackson.annotation.JsonProperty;
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    // Junit class
    public class TableDeserExample {
        // sample input
        String inputJson = "{\n" +
                "    \"Results\": {\n" +
                "        \"output1\": {\n" +
                "            \"type\": \"table\",\n" +
                "            \"value\": {\n" +
                "                \"ColumnNames\": [\"userId\", \"documentId\", \"Scored Labels\", \"Scored Probabilities\"],\n" +
                "                \"ColumnTypes\": [\"String\", \"String\", \"Boolean\", \"Double\"],\n" +
                "                \"Values\": [[\"100213199594809000000\", \"1Ktol-SWvAh8pnHG2O7HdPrfbEVZWX3Vf2YIPYXA_8gI\", \"False\", \"0.375048756599426\"], [\"103097844766994000000\", \"1jYsTPJH8gaIiATix9x34Ekcj31ifJMkPNb0RmxnuGxs\", \"True\", \"0.753859758377075\"]]\n"
                +
                "            }\n" +
                "        }\n" +
                "    }\n" +
                "}";
    
        // POJO to map the Json structure. You may want to make it generalize based
        // on field "type"
        // (https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization)
        public static class Result {
            private String type;
            private TableResult value;
    
            public String getType() {
                return this.type;
            }
    
            public void setType(String type) {
                this.type = type;
            }
    
            public void setValue(TableResult value) {
                this.value = value;
            }
    
            public TableResult getValue() {
                return this.value;
            }
        }
    
        // Pojo for table result
        public static class TableResult {
            private List<String> columnNames;
            private List<String> columnTypes;
            private List<Object[]> values;
    
            @JsonProperty("ColumnNames")
            public List<String> getColumnNames() {
                return this.columnNames;
            }
    
            public void setColumnNames(List<String> columnNames) {
                this.columnNames = columnNames;
            }
    
            @JsonProperty("ColumnTypes")
            public List<String> getColumnTypes() {
                return this.columnTypes;
            }
    
            public void setColumnTypes(List<String> columnTypes) {
                this.columnTypes = columnTypes;
            }
    
            @JsonProperty("Values")
            public List<Object[]> getValues() {
                return this.values;
            }
    
            public void setValues(List<Object[]> values) {
                this.values = values;
            }
    
        }
    
        // Top level Json POJO
        public static class ResultContainer {
            private Map<String, Result> results;
    
            @JsonProperty("Results")
            public Map<String, Result> getResults() {
                return this.results;
            }
    
            public void setResults(Map<String, Result> results) {
                this.results = results;
            }
        }
    
        // A contract to map the result "values" to the expected object
        public static interface ResultMapper<T> {
            T map(TableResult map, Object[] row);
        }
    
        // Basic implementation for mapping user object from json "values[i]" array
        public static class UserTableResultMapper implements ResultMapper<User> {
    
            @Override
            public User map(TableResult result, Object[] row) {
                User user = new User();
                // Here use any mapper logic based on column name
                // Retrieved from result object.
                // Below are for illustration only
                user.setId(String.valueOf(row[0]));
                user.setDocumentId(String.valueOf(row[1]));
                return user;
            }
    
        }
    
        // A result reader class
        public static class ResultReader<T> implements Iterable<T> {
            private TableResult result;
            private ResultMapper<T> mapper;
    
            public ResultReader(TableResult result, ResultMapper<T> mapper) {
                this.result = result;
                this.mapper = mapper;
            }
    
            @Override
            public Iterator<T> iterator() {
                final Iterator<Object[]> itr = result.getValues().iterator();
                return new Iterator<T>() {
    
                    @Override
                    public void remove() {
                        throw new UnsupportedOperationException();
                    }
    
                    @Override
                    public T next() {
                        Object[] values = itr.next();
                        return mapper.map(result, values);
                    }
    
                    @Override
                    public boolean hasNext() {
                        return itr.hasNext();
                    }
                };
            };
        }
    
        public static class User {
            private String id;
            private String documentId;
            // and others
    
            public String getId() {
                return this.id;
            }
    
            public void setDocumentId(String documentId) {
                this.documentId = documentId;
            }
    
            public void setId(String id) {
                this.id = id;
            }
    
            public String getDocumentId() {
                return this.documentId;
            }
    
        }
    
        @Test
        public void simpleTest() throws Exception {
            ObjectMapper mapper = new ObjectMapper();
            ResultContainer file = mapper.readValue(inputJson, ResultContainer.class);
            Result result = file.getResults().get("output1");
            ResultReader<User> userResultReader = new ResultReader<>(result.getValue(), new UserTableResultMapper());
            for (User user : userResultReader) {
                System.out.println(user.getId() + " : " + user.getDocumentId());
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      如果您确切知道 json 的结构(例如您发布的 json),那么您可以使用 Gson 来获取您的对象,如下所示:

      JsonParser parser = new JsonParser();
      JsonObject json = (JsonObject) parser.parse("your_json_string_here");
      String column = json.get("Results").getAsJsonObject().get("output1").getAsJsonObject().get("value").getAsJsonObject().get("ColumnNames").getAsJsonArray().toString();
      String value = json.get("Results").getAsJsonObject().get("output1").getAsJsonObject().get("value").getAsJsonObject().get("Values").getAsJsonArray().toString();    
      System.out.println(column);
      System.out.println(value);
      

      如果您需要一些更通用的东西,那么您可以将 json 字符串解析为 HashMap&lt;String, Object&gt;,然后使用递归读取 HashMap 并获得您想要的值。 示例(在我的代码中,Map的类型将对应一个Json Object,List的类型将对应Json字符串中的Array):

      Type type = new TypeToken<HashMap<String, Object>>() {}.getType();
      Gson gson = new Gson();
      HashMap<String, Object> map = gson.fromJson("your_json_string_here", type);
          for (String key : map.keySet()) {
              Object obj = map.get(key);
              if (obj instanceof List) {
                  for (Object o : (List) obj) {
                      if (o instanceof Map) {
                          loop((Map) o);
                      } else {
                          System.out.println(key + " : " + o);
                      }
                  }
              } else if (obj instanceof Map) {
                  loop((Map) obj);
              } else {
                  System.out.println(key + " : " + obj);
              }
          }
      }
      
      private static void loop(Map<String, Object> map) {
          for (String key : map.keySet()) {
              Object obj = map.get(key);
              if (obj instanceof List) {
                  for (Object o : (List) obj) {
                      if (o instanceof Map) {
                          loop((Map) o);
                      } else {
                          System.out.println(key + " : " + o);
                      }
                  }
              } else if (obj instanceof Map) {
                  loop((Map) obj);
              } else {
                  System.out.println(key + " : " + obj);
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        Jackson 和任何其他库都不会将 Values 数组解析为具有客户端数据的对象,例如您的 POJO。您可以通过获取此 JSON 中的原始数据树并通过迭代此树中的 Values 数组来构造对象来实现此目的。假设ColumnNames 的顺序是固定的,那么您可以像这样使用Jackson 进行解析:

        final ObjectMapper mapper = new ObjectMapper();
        final JsonNode tree = mapper.readTree(json);
        final JsonNode values = tree.findValue("Values");
        
        final List<ClientPOJO> clients = new ArrayList<>();
        for (JsonNode node : values) {
            final ClientPOJO client = new ClientPOJO();
            client.setUserId(node.get(0).asText());
            client.setDocumentId(node.get(1).asText());
            client.setScoredLabels(node.get(2).asBoolean());
            client.setScoredProbabilities(node.get(3).asDouble());
            clients.add(client);
        }
        

        JsonNode 的文档。基本上,findValue 可以让另一个节点深入到树中,get 可以通过索引获取数组元素,asText 等可以将 JSON 中的值解析为 Java 中的适当类型。

        由于您似乎可以灵活地选择 JSON 解析库,我建议您尝试使用来自 com.fasterxml 的 Jackson 2 而不是来自 org.codehaus 的 Jackson 1。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-06-21
          • 2012-08-07
          • 2021-12-31
          • 2020-10-09
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多