2017-06-24 30 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()); 
     } 
    } 
}