2015-04-24 19 views
7

Tôi đang cố gắng sử dụng trình phân tích cú pháp json Jackson (v2.5.2) để phân tích cú pháp tài liệu json tùy chỉnh không đúng json và tôi không thể tìm ra cách lam cho no hoạt động. Tôi có một tài liệu json có thể trông giống như:Xử lý ngoại lệ "Mã thông báo không xác định" trong json tùy chỉnh với Jackson

{ 
    "test": { 
     "one":"oneThing", 
     "two": nonStandardThing(), 
     "three": true 
    } 
} 

Tôi muốn sử dụng ObjectMapper để lập bản đồ này cho một người java.util.Map và tôi sẽ giống như nonStandardThing() được thêm vào như là một giá trị String trong bản đồ của tôi cho phím two .

Khi tôi chạy qua ObjectMapper.readValue(json, Map.class) tôi nhận được ngoại lệ:

com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'nonStandardThing': was expecting 'null', 'true', 'false' or NaN 
at [Source: { "test":{"test1":nonStandardThing(),"test2":"two"}}; line: 1, column: 35] 
    at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1487) 
    at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:518) 
    at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2300) 
    at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2277) 

Tôi đã thử đăng ký một DeserializationProblemHandler với ObjectMapper nhưng nó không bao giờ được gọi là khi vấn đề này xảy ra.

Đây là ứng dụng mẫu cho thấy những gì tôi đã cố gắng:

import com.fasterxml.jackson.core.JsonParser; 
import com.fasterxml.jackson.core.JsonProcessingException; 
import com.fasterxml.jackson.databind.DeserializationContext; 
import com.fasterxml.jackson.databind.JsonDeserializer; 
import com.fasterxml.jackson.databind.ObjectMapper; 
import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler; 
import java.io.IOException; 
import java.util.Map; 
import java.util.logging.Level; 
import java.util.logging.Logger; 

public class JacksonDeserializerTest { 
    private Logger log = Logger.getLogger(JacksonDeserializerTest.class.getName()); 
    public JacksonDeserializerTest() { 
     String validJson = "{ \"test\":{\"test1\":\"one\",\"test2\":\"two\"}}"; 
     String invalidJson = "{ \"test\":{\"test1\":nonStandardThing(),\"test2\":\"two\"}}"; 

     ObjectMapper mapper = new ObjectMapper(); 
     mapper.addHandler(new DeserializationProblemHandler() { 
      @Override 
      public boolean handleUnknownProperty(DeserializationContext dc, JsonParser jp, JsonDeserializer<?> jd, Object bean, String property) throws IOException, JsonProcessingException { 
       System.out.println("Handling unknown property: " + property); 
       return false; 
      } 
     }); 

     try { 
      log.log(Level.INFO, "Valid json looks like: {0}", mapper.readValue(validJson, Map.class).toString()); 
      log.log(Level.INFO, "Invalid json looks like: {0}", mapper.readValue(invalidJson, Map.class).toString()); 
     } catch (IOException ex) { 
      log.log(Level.SEVERE, "Error parsing json", ex); 
     } 

    } 

    public static void main(String[] args) { 
     JacksonDeserializerTest test = new JacksonDeserializerTest(); 
    } 
} 

Kết quả trông giống như:

Apr 24, 2015 1:40:27 PM net.acesinc.data.json.generator.jackson.JacksonDeserializerTest <init> 
INFO: Valid json looks like: {test={test1=one, test2=two}} 
Apr 24, 2015 1:40:27 PM net.acesinc.data.json.generator.jackson.JacksonDeserializerTest <init> 
SEVERE: Error parsing json 
com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'nonStandardThing': was expecting 'null', 'true', 'false' or NaN 
at [Source: { "test":{"test1":nonStandardThing(),"test2":"two"}}; line: 1, column: 35] 
    at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1487) 
    at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:518) 
    at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2300) 
    at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2277) 
    at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._matchToken(ReaderBasedJsonParser.java:2129) 

bất cứ ai có thể chỉ ra lý do tại sao các Handler không bao giờ được gọi là? Hoặc, nếu có phân tích tốt hơn tài liệu json tùy chỉnh này (jackson hay không ...), hãy cho tôi biết.

Trả lời

7

Trình xử lý không được gọi vì phần không hợp lệ không phải là tài sản ("two") nhưng giá trị (nonStandardThing()).

Một cách rõ ràng để xử lý việc này, là để vượt qua nonStandardThing() như một String, ví dụ: viết lại tài liệu JSON như

{ 
    "test": { 
     "one":"oneThing", 
     "two": "nonStandardThing()", 
     "three": true 
    } 
} 

Nếu đó không phải là một khả năng, không có nhiều việc phải làm. Sử dụng tùy chỉnh JacksonDeserializer chỉ hữu ích cho các thuộc tính, không phải giá trị.

+0

Và bởi 'Jackson Deserializer', bạn có nghĩa là một tùy chỉnh java.util.Map Deserializer? Đó là những gì tôi đã lo lắng về ... –

+1

Thậm chí không có điều đó sẽ cung cấp một giải pháp. Từ các cuộc thảo luận trong danh sách gửi thư của Jackson, rõ ràng là chức năng cần thiết hiện đang tồn tại cho các thuộc tính chứ không phải các giá trị. Có lẽ bạn không kiểm soát được quá trình tuần tự hóa? 1 cho một câu hỏi thú vị anyway. :-) – PNS

+0

Vâng, tôi thực sự có thể thay đổi định dạng này, nhưng điều thú vị là 'Jackson' không cho phép bạn xử lý giá trị. Rất tiếc, điều đó có thể xảy ra lần nữa. Tôi cho rằng bạn có thể tiền xử lý các json để trích dẫn các giá trị không chuẩn và làm cho nó hợp lệ. Trong mọi trường hợp, câu trả lời của bạn (mà đã vượt qua tâm trí của tôi trước đó) đã cho tôi suy nghĩ về vấn đề một cách khác nhau một lần nữa và bây giờ tôi đang làm lại những điều để phù hợp với điều này tốt hơn. Cảm ơn! –

2

Nội dung bạn liệt kê không may là không hợp lệ JSON, vì vậy những gì bạn có không thực sự là một tài liệu JSON, nhưng có lẽ tuần tự hóa đối tượng Javascript. Tất cả các giá trị chuỗi phải được kèm theo trong dấu ngoặc kép trong JSON.

Jackson không hỗ trợ đọc trực tiếp nội dung đó, nhưng có thể đọc được điều này bằng cách sử dụng trình phân tích cú pháp YAML như SnakeYAML. Jackson cũng có mô-đun định dạng dữ liệu YAML tại https://github.com/FasterXML/jackson-dataformat-yaml/ để bạn có thể sử dụng nó. Cho rằng YAML (chủ yếu là!) Là một siêu của JSON, nó có thể làm những gì bạn muốn.

+0

Cảm ơn các đề xuất về trình phân tích cú pháp YAML! Tôi sẽ phải thử lần sau. –

Các vấn đề liên quan