2017-03-14 61 views
2

我有一個JSON文件,其中有幾個包含重複值的文本數組。例如:使用Jackson從所有JSON數組中刪除重複的文本值

{ 
    "mName": "Carl Sanchez", 
    "mEmailID": "[email protected]", 
    "mPhoneNo": 7954041324, 

    "tutorTypes": [ 
     " Freelancer/Professional Tutor", 
     " Freelancer/Professional Tutor", 
     " Coaching Institute Teacher ", 
     " Corporate Professional ", 
     " Freelancer/Professional Tutor", 
     " Freelancer/Professional Tutor", 
     " Freelancer/Professional Tutor", 
     " Freelancer/Professional Tutor", 
     " Freelancer/Professional Tutor", 
     " Freelancer/Professional Tutor", 
     " Freelancer/Professional Tutor", 
     " Freelancer/Professional Tutor", 
     " Freelancer/Professional Tutor" 
    ], 
    "disciplines": [ 
     " Japanese", 
     " German ", 
     " Japanese", 
     " German ", 
     " Japanese", 
     " Hindi ", 
     " Japanese", 
     " French " 
    ] 
} 

我想刪除JSON源中所有數組的重複值(文本值)。在上面的例子中,這將是從數組中刪除重複的語言和輔導類型。所需的輸出將是上述JSON源,只需在適用的情況下刪除重複值。此外,我不希望將代碼綁定到特定的JSON字段名稱,而是通常的任何文本值數組。在上面的例子中所需的輸出將是,

{ 
    "mName": "Carl Sanchez", 
    "mEmailID": "[email protected]", 
    "mPhoneNo": 7954041324, 

    "tutorTypes": [ 
     " Freelancer/Professional Tutor", 
     " Coaching Institute Teacher ", 
     " Corporate Professional " 
    ], 
    "disciplines": [ 
     " Japanese", 
     " German ", 
     " Hindi ", 
     " French " 
    ] 
} 

JSON的輸入源是一個文件,我想要寫在文件中的輸出。 我試圖程序來完成這項傑克遜使用數據綁定API:

public static void removeDuplicateStringElementsFromAllArrays(String file) throws IOException { 

     Writer fileWriter = new BufferedWriter(new FileWriter(new File("out.json"))); 

     JsonFactory f = new MappingJsonFactory(); 
     JsonParser jp = f.createJsonParser(new File(file)); 

     parse(jp, fileWriter); 
    } 

    private static void parse(JsonParser jp, Writer writer) throws IOException{ 
     JsonToken current; 
     current = jp.nextToken(); 

     if(current != null){ 
      System.out.println(current.asString()); 
      writer.write(current.asString()); 
     } 

     if(current == JsonToken.START_ARRAY){ 
      if(jp.nextTextValue() != null){ 
       JsonNode node = jp.readValueAsTree(); 
       // Trim the String values 
       String[] values = ArraysUtil.trimArray("\"" , node.toString().split(","), "\""); 
       // Ensure that there is no duplicate value 
       values = new HashSet<String>(Arrays.asList(values)).toArray(new String[0]); 
       // Finally, concatenate the values back and stash them to file 
       String concatValue = String.join(",", values); 

       // Write the concatenated values to file 
       writer.write(concatValue); 
      } 
      else{ 
       parse(jp, writer); 
      } 
     } 
     else{ 
      // Move on directly 
      parse(jp, writer); 
     } 
    } 

我得到幾個空值作爲輸出。我知道爲什麼會發生這種情況。我想,當我打電話給jp.nextTextValue()時,解析器已經開始工作,構建一個值樹可能導致了這種情況,但我無法找出任何解決方法。有誰知道,我怎麼去完成這項任務。

編輯:

只是想在這裏補充說明一兩件事 - 我使用的是傑克遜,數據綁定API,因爲它是建立在流API解析一個大的JSON源,這是我的情況時,這是有效的。所以,考慮到這一點的解決方案將不勝感激。

回答

0

這是一個使用Json Simple的例子。請注意,這假設數組存在於根級別,並且不檢查每個參數中的嵌套數組。如果你想支持

package test.json.jsonsimple; 

import java.io.FileNotFoundException; 
import java.io.FileReader; 
import java.io.FileWriter; 
import java.io.IOException; 
import java.util.HashSet; 
import java.util.Iterator; 
import java.util.Map; 
import java.util.Set; 

import org.json.simple.JSONArray; 
import org.json.simple.JSONObject; 
import org.json.simple.parser.JSONParser; 
import org.json.simple.parser.ParseException; 

public class App 
{ 
    @SuppressWarnings("unchecked") 
    public static void main(String[] args) 
    { 
     System.out.println("Hello World!"); 

     JSONParser parser = new JSONParser(); 

     try { 
      JSONObject outmap = new JSONObject(); 
      Object obj = parser.parse(new FileReader("d:\\in.json")); 
      JSONObject jsonObject = (JSONObject) obj; 
      for(Object o : jsonObject.entrySet()){ 
       if(o instanceof Map.Entry){ 
        Map.Entry<String, Object> entry = (Map.Entry<String, Object>) o; 
        if(entry !=null){ 
         if(entry.getValue() instanceof JSONArray){ 
          Set<String> uniqueValues = removeDuplicates(entry.getValue()); 
          outmap.put(entry.getKey(), uniqueValues); 
         }else{ 
          outmap.put(entry.getKey(), entry.getValue()); 
         } 
        } 
       } 
      } 

      FileWriter file = new FileWriter("d:\\out.json"); 
      file.write(outmap.toJSONString()); 
      file.flush(); 
      file.close(); 

     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (ParseException e) { 
      e.printStackTrace(); 
     } 

    } 

    @SuppressWarnings("unchecked") 
    private static Set<String> removeDuplicates(Object value) { 
     Set<String> outset = new HashSet<String>(); 
     JSONArray inset = (JSONArray) value; 

     if (inset != null) { 
      Iterator<String> iterator = inset.iterator(); 
      while (iterator.hasNext()) { 
       outset.add(iterator.next()); 
      } 
     } 
     return outset; 
    } 
} 
3

創建一個bean Contact.java和您要刪除重複Set聲明屬性,您可以添加一個遞歸的邏輯。

當您序列化JSON時,Set將執行刪除重複項的工作。不需要額外的代碼。

package com.tmp; 

import java.util.Set; 

public class Contact { 

    String  mName; 
    String  mEmailID; 
    long  mPhoneNo; 

    Set<String> tutorTypes; // to remove duplicates 
    Set<String> disciplines; // to remove duplicates 

    // setter and getter methods goes here...  
} 

刪除重複

package com.tmp; 

import java.io.File; 
import java.io.IOException; 

import com.fasterxml.jackson.databind.ObjectMapper; 


/** 
* 
* @author Ravi P 
*/ 
class Tmp { 

    public static void main(String[] args) throws IOException { 

     ObjectMapper mapper = new ObjectMapper(); 

     Contact contact = mapper.readValue(new File("D:\\tmp\\file.json"), Contact.class); 

     mapper.writeValue(new File("D:\\tmp\\file1.json"), contact); 

    } 
}