[英]How to parse JSON log file with Streaming API in Java, then output tabulated log file
我有一個問題,我試圖解析以JSON格式存儲的大型日志文件,然后將數據列表並輸出為另一個JSON文件。 以下是我正在解析的日志文件的格式:
{
"timestamp": "2012-10-01TO1:00:00.000",
"id": "someone@somewhere.net",
"action": "Some_Action"
"responsecode": "1000"
}
此處的操作是某些用戶執行的操作,響應代碼是該操作的結果。
時間戳和id實際上與我的制表無關,我只對動作/代碼字段感興趣。 在任何給定的日志文件中可能有數萬個這樣的條目,我想要做的是跟蹤所有類型的操作 , 響應代碼及其各自的出現次數。
下面是我想要生成的輸出的示例。
{"actionName": "Some_User_Action",
"responses": [{"code": "1000", "count": "36"},
{"code": "1001", "count": "6"},
{"code": "1002", "count": "3"},
{"code": "1003", "count": "36"},
{"code": "1004", "count": "2"}],
"totalActionCount": "83"}
所以基本上,對於每個Action,我想跟蹤它生成的所有不同響應以及每個響應發生的次數。 最后,我想跟蹤該行動的總回復總數。
目前,我已經為輸出對象創建了一個Java類,我計划在其中存儲輸出數據。 我也對我應該存儲響應數組的格式和它們各自的計數數字有點困惑。 響應代碼類型的總數也因Action而異。
根據我的研究,我似乎需要使用Streaming API來使用JSON解析。 使用Streaming API的原因主要是由於使用非流API需要的內存開銷量,這可能與這些日志文件的大小無法實現。 我目前正在考慮使用Jackson或GSON,但我無法找到任何具體的示例或教程來幫助我入門。 有誰知道一個很好的例子,我可以學習或有任何關於如何解決這個問題的提示? 謝謝!
編輯:我的班級定義。
public class Action {
public static class Response {
private int _resultCode;
private int _count = 0;
public Response() {}
public int getResultCode() { return _resultCode; }
public int getCount() { return _count; }
public void setResultCode(int rc) { _resultCode = rc; }
public void setCount(int c) { _count = c; }
}
private List<Response> responses = new ArrayList<Response>();
private String _name;
// I've left out the getters/setters and helper functions that I will add in after.
}
如果我正在使用Jackson,並希望最終能夠輕松地將此對象序列化回JSON,那么我是否有關於如何定義此類的建議? 目前我在main()方法中使用以下方法創建此Action類型的另一個ArrayList:List actions = new ArrayList(); 使用HashMaps或其他替代品是更好的選擇嗎? 此外,它是否允許我使用傑克遜輕松將其序列化為JSON?
好的,首先,傑克遜可以將數據綁定與流媒體相結合。 您只需要一個JsonParser
(使用JsonFactory
創建,其實例可以從ObjectMapper
,或直接構造)。 然后,您可以將流提前到第一個條目,並從那里開始使用數據綁定( ObjectMapper.readValue(...)
)。 這只會讀取獲取所需單個值實例所需的最小值。
甚至更好,一旦到達陣列,使用“readValues()”方法
ObjectMapper mapper = new ObjectMapper();
JsonParser jp = mapper.getJsonFactory().createJsonParser(sourceFile);
while (jp.nextToken() != JsonToken.START_ARRAY) { }
MappingIterator<Response> it = mapper.readValues(jp, Entry.class);
while (it.hasNextValue()) {
Response value = it.nextValue();
// process it; keep count, whatever
}
要輸出,您可能需要考慮Jackson CSV模塊 :它可以使用CSV變體之一來寫入條目; 你可以將分隔符重新定義為你喜歡的任何東西。 有關示例,請參閱項目自述文件
您可以查看Genson庫http://code.google.com/p/genson/ ,在Wiki頁面上,您將找到有關如何使用它的一些示例。 自首次發布以來,它提供了流媒體模型,並且似乎是傑克遜之后最快的,見基准 。
如果你想做一些真正有效的事情並且內存占用量很小,可以通過實例化JsonReader直接使用流式api,然后使用它來讀取記錄的結構並增加你的計數器。
否則你可以使用Genson實例直接將文件解析為java對象,但在你的情況下我不認為它是正確的解決方案,因為它需要你將所有對象存儲在內存中!
以下是直接使用流式api的快速示例。 它不會精確打印您期望的結構,因為它需要更多代碼來有效地計算您的結構:
public static void main(String[] args) throws IOException, TransformationException {
Map<String, Map<String, Integer>> actions = new HashMap<String, Map<String, Integer>>();
Genson genson = new Genson();
ObjectReader reader = genson.createReader(new FileReader("path/to/the/file"));
while(reader.hasNext()) {
reader.next();
reader.beginObject();
String action = readUntil("action", reader);
// assuming the next name/value pair is responsecode
reader.next();
String responseCode = reader.valueAsString();
Map<String, Integer> countMap = actions.get(action);
if (countMap == null) {
countMap = new HashMap<String, Integer>();
actions.put(action, countMap);
}
Integer count = countMap.get(responseCode);
if (count == null) {
count = 0;
}
count++;
countMap.put(responseCode, count);
reader.endObject();
}
// for example if you had 2 different response codes for same action it will print
// {"Some_Action":{"1001":1,"1000":1}}
String json = genson.serialize(actions);
}
static String readUntil(String name, ObjectReader reader) throws IOException {
while(reader.hasNext()) {
reader.next();
if (name.equals(reader.name())) {
return reader.valueAsString();
}
}
throw new IllegalStateException();
}
您可以逐個解析您的記錄,因此我不認為JSON結構的內存消耗超過幾千字節。 只是創造
class Something {
String action;
int responsecode;
// do not include the fields you don't need
}
並在每一步中讀取一條記錄。 Guava的HashMultiset<String, Integer>
及其方法put
, count
和size
為您提供所需的一切。 如果你的內存耗盡(因為巨大的Multimap),你可能需要一個數據庫,但我先嘗試一下這個簡單的解決方案。
對於輸出JSON,您可能需要GSON的TypeAdapter
或JsonSerializer
。 或者作為黑客,您可以輕松地手動生成輸出。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.