@Override
 public RegisterMessageImpl deserialize(final JsonParser jp, final DeserializationContext ctxt)
     throws IOException, JsonProcessingException {
   final ObjectCodec oc = jp.getCodec();
   final JsonNode node = oc.readTree(jp);
   return new RegisterMessageImpl(node.get(RegisterMessage.CHANNEL_ID_FIELD).asText());
 }
 @Override
 public RnRColumnSource deserialize(JsonParser jsonParser, DeserializationContext ctxt)
     throws IOException {
   ObjectCodec oc = jsonParser.getCodec();
   JsonNode node = oc.readTree(jsonParser);
   return RnRColumnSource.getValueOf(node.get("code").getTextValue());
 }
 @Override
 public HelloResponseImpl deserialize(final JsonParser jp, final DeserializationContext ctxt)
     throws IOException, JsonProcessingException {
   final ObjectCodec oc = jp.getCodec();
   final JsonNode node = oc.readTree(jp);
   final JsonNode uaid = node.get(HelloMessage.UAID_FIELD);
   return new HelloResponseImpl(UUID.fromString(uaid.asText()).toString());
 }
  @Override
  public Geometry deserialize(JsonParser jp, DeserializationContext ctxt)
      throws IOException, JsonProcessingException {

    ObjectCodec oc = jp.getCodec();
    JsonNode root = oc.readTree(jp);
    return parseGeometry(root);
  }
 @Override
 public PingMessageImpl deserialize(final JsonParser jp, final DeserializationContext ctxt)
     throws IOException, JsonProcessingException {
   final ObjectCodec oc = jp.getCodec();
   final JsonNode node = oc.readTree(jp);
   if (node.isObject() && node.size() == 0) {
     return new PingMessageImpl(node.toString());
   }
   throw new RuntimeException("Invalid Ping message format : [" + node.toString() + "]");
 }
 @Override
 public RegisterResponseImpl deserialize(final JsonParser jp, final DeserializationContext ctxt)
     throws IOException, JsonProcessingException {
   final ObjectCodec oc = jp.getCodec();
   final JsonNode node = oc.readTree(jp);
   return new RegisterResponseImpl(
       node.get(RegisterMessage.CHANNEL_ID_FIELD).asText(),
       new StatusImpl(node.get(RegisterResponseImpl.STATUS_FIELD).asInt(), "N/A"),
       node.get(RegisterResponseImpl.PUSH_ENDPOINT__FIELD).asText());
 }
 @Override
 public UnregisterResponseImpl deserialize(
     final JsonParser jp, final DeserializationContext ctxt)
     throws IOException, JsonProcessingException {
   final ObjectCodec oc = jp.getCodec();
   final JsonNode node = oc.readTree(jp);
   final JsonNode channelIdNode = node.get(RegisterResponse.CHANNEL_ID_FIELD);
   return new UnregisterResponseImpl(
       channelIdNode.asText(),
       new StatusImpl(node.get(UnregisterResponse.STATUS_FIELD).asInt(), "N/A"));
 }
 @Override
 public MessageType deserialize(final JsonParser jp, final DeserializationContext ctxt)
     throws IOException, JsonProcessingException {
   final ObjectCodec oc = jp.getCodec();
   final JsonNode node = oc.readTree(jp);
   final JsonNode messageTypeNode = node.get(MessageType.MESSSAGE_TYPE_FIELD);
   return new MessageType() {
     @Override
     public Type getMessageType() {
       if (messageTypeNode == null) {
         return MessageType.Type.PING;
       }
       return MessageType.Type.valueOf(messageTypeNode.asText().toUpperCase());
     }
   };
 }
 @Override
 public AckMessageImpl deserialize(final JsonParser jp, final DeserializationContext ctxt)
     throws IOException, JsonProcessingException {
   final ObjectCodec oc = jp.getCodec();
   final JsonNode node = oc.readTree(jp);
   final JsonNode updatesNode = node.get(AckMessage.UPDATES_FIELD);
   final Set<Update> updates = new HashSet<Update>();
   if (updatesNode.isArray()) {
     for (JsonNode updateNode : updatesNode) {
       updates.add(
           new UpdateImpl(
               updateNode.get("channelID").asText(), updateNode.get("version").asLong()));
     }
   }
   return new AckMessageImpl(updates);
 }
 @Override
 public NotificationMessageImpl deserialize(
     final JsonParser jp, final DeserializationContext ctxt)
     throws IOException, JsonProcessingException {
   final ObjectCodec oc = jp.getCodec();
   final JsonNode node = oc.readTree(jp);
   final JsonNode updatesNode = node.get(NotificationMessage.UPDATES_FIELD);
   final Set<Update> updates = new HashSet<Update>();
   if (updatesNode.isArray()) {
     for (JsonNode channelNode : updatesNode) {
       final JsonNode versionNode = channelNode.get(NotificationMessage.VERSION_FIELD);
       final JsonNode channelIdNode = channelNode.get(RegisterMessage.CHANNEL_ID_FIELD);
       updates.add(new UpdateImpl(channelIdNode.asText(), versionNode.asLong()));
     }
   }
   return new NotificationMessageImpl(updates);
 }
 @Override
 public HelloMessageImpl deserialize(final JsonParser jp, final DeserializationContext ctxt)
     throws IOException, JsonProcessingException {
   final ObjectCodec oc = jp.getCodec();
   final JsonNode node = oc.readTree(jp);
   final JsonNode channelIdsNode = node.get(HelloMessage.CHANNEL_IDS_FIELD);
   final Set<String> channelIds = new HashSet<String>();
   if (channelIdsNode != null && channelIdsNode.isArray()) {
     for (JsonNode channelIdNode : channelIdsNode) {
       channelIds.add(channelIdNode.asText());
     }
   }
   final JsonNode uaid = node.get(HelloMessage.UAID_FIELD);
   if (uaid != null) {
     return new HelloMessageImpl(node.get(HelloMessage.UAID_FIELD).asText(), channelIds);
   } else {
     return new HelloMessageImpl();
   }
 }