Search code examples
jsonjava-8jacksonjsonpathjsonparser

Parsing JSON into list of Java POJOs using JSurfer or similar


Java 8 here, trying to use the JSurfer library, however I will accept just about any efficient solution that works.

I am being given a string containing (for example) the following JSON:

[
  {
    "email": "example@test.com",
    "timestamp": 1589482169,
    "smtp-id": "<14c5d75ce93.dfd.64b469@ismtpd-555>",
    "event": "processed",
    "category": "cat facts",
    "sg_event_id": "5Gp2JunPL_KgVRV3mqsbcA==",
    "sg_message_id": "14c5d75ce93.dfd.64b469.filter0001.16648.5515E0B88.0"
  },
  {
    "email": "example@test.com",
    "timestamp": 1589482169,
    "smtp-id": "<14c5d75ce93.dfd.64b469@ismtpd-555>",
    "event": "deferred",
    "category": "cat facts",
    "sg_event_id": "KnIgbwNwADlShGoflQ4lTg==",
    "sg_message_id": "14c5d75ce93.dfd.64b469.filter0001.16648.5515E0B88.0",
    "response": "400 try again later",
    "attempt": "5"
  }
]

I want to parse the JSON array and, for each object in the array, cherry pick/extract the event and sg_event_id fields and use them to populate a new WebhookEvent POJO instance. I should be left with a List<WebhookEvent> list like so:

public class WebhookEvent {

  private String event;
  private String sgEventId;

  // getters, setters and ctor omitted for brevity

}

then:

public class EventParser {

  private JsonSurfer jsonSurfer = JsonSurferJackson.INSTANCE;

  public List<WebhookEvent> parseJsonToWebhookEventList(String json) {

    List<WebhookEvent> webhookEvents = new ArrayList<>();

    // for each object in the json array, instantiate a pluck out the event/sg_event_id fields
    // into a new WebhookEvent instance, and then add that instance to our list
    SurfingConfiguration surferConfig = jsonSurfer.configBuilder()
      .bind("??? (1) not sure what to put here ???", new JsonPathListener() {
          @Override
          public void onValue(Object value, ParsingContext context) {

              WebhookEvent webhookEvent = new WebhookEvent();
              webhookEvent.setEvent("??? (2) not sure how to pluck this out of value/context ???");
              webhookEvent.setSgEventId("??? (3) not sure how to pluck this out of value/context ???");

              webhookEvents.add(webhookEvent);

          }
      }).build();

      return webhooks;

  }
}

I'm struggling with a few areas in the code snippet above:

  1. how to write the proper jsonpath to specify the objects in my array
  2. how to pluck out the event and sg_event_id values from inside the listener

Again, I'm not married to JsonSurfer, so I'll take just about any solution that works (Jackson, GSON, etc.). However I'm not interested in mapping the JSON to POJOs the way Jackson typically does. Thanks in advance for any-and-all-help!


Solution

  • Using GSON

    public class GsonExample{
    
        public static void main(String[] args) throws JsonProcessingException {
            List<WebhookEvent> webhookEvents = new Gson().fromJson("YOUR JSON STRING", new TypeToken<List<WebhookEvent>>(){}.getType());
            webhookEvents.forEach(item -> {
                System.out.println(item);
            });
        }
    }
    
    class WebhookEvent {
    
        private String event;
        @SerializedName(value="sg_event_id") // as attribute name in pojo and json are different
        private String sgEventId;
    
        // getters, setters and ctor omitted for brevity
    
    }
    

    Using Jackson

    I am not sure why you are against using it.

    public class JacksonExample4 {
    
        public static void main(String[] args) throws JsonProcessingException {
            ObjectMapper objectMapper = new ObjectMapper();
            List<WebhookEvent> webhookEvents = objectMapper.readValue("YOUR JSON STRING", new TypeReference<List<WebhookEvent>>(){});
            webhookEvents.forEach(item -> {
                System.out.println(item);
            });
        }
    }
    
    @JsonIgnoreProperties(ignoreUnknown = true)// To ignore attributes present in json but not in pojo
    class WebhookEvent {
    
        private String event;
        @JsonProperty("sg_event_id")// as attribute name in pojo and json are different
        private String sgEventId;
        // toString() overidden
    
        // getters, setters and ctor omitted for brevity
    
    }
    

    Output for both GSON and Jackson:

    WebhookEvent(event=processed, sgEventId=5Gp2JunPL_KgVRV3mqsbcA==) WebhookEvent(event=deferred, sgEventId=KnIgbwNwADlShGoflQ4lTg==)