2017-06-24 25 views
1

我有这些JSON字符串:JSON字符串为Java String

{ 
    "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: [email protected]; 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: [email protected]; line: 1, column: 2] 
+0

您是否必须使用jackson或可以使用其他JSON库? – Pshemo

+0

其他库文也适合我。重点在于,我必须以seperat形式获取userId,documentID和得分标签。我需要这个,因为我以后会发送这个。 – Tim1234

+0

在这种情况下,请看看其他问题,如https://stackoverflow.com/questions/11874919/parsing-json-string-in-java。所有你需要做的就是获取由“结果”键保存的json对象,然后从该对象获取由“值”键保存的对象。从那里只需要获取“ColumnNames”和“Values”的json数组。 – Pshemo

回答

0

如果你知道你的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<String, Object>,然后使用递归读取HashMap并获取所需的值。 实施例(在我的代码,地图的类型将对应于一个JSON对象,列表的类型将对应于JSON字符串数组):

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); 
     } 
    } 
} 
0

既不杰克逊或任何其他文库将解析Values阵列分为带有客户端数据的对象,比如你的POJO。您可以通过获取此JSON中的原始数据树并通过遍历此树中的Values数组构建对象来实现此目的。假设ColumnNames的顺序是固定的,那么你可以与杰克逊分析是这样的:

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

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

由于您在选择JSON解析库时似乎很灵活,所以我建议从com.fasterxml中选择Jackson 2而不是您尝试的org.codehaus中的Jackson 1。

0

下面是一个例子来说明解决你的问题的一般方法(基于杰克逊库)。您可能想要增强解决方案以满足您的所有要求。

评论内置。

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