2

I got this error when is trying to deserialize a URL

Caused by: java.net.MalformedURLException: no protocol: www.boo.com
    at java.net.URL.<init>(URL.java:586) ~[na:1.8.0_45]
    at java.net.URL.<init>(URL.java:483) ~[na:1.8.0_45]
    at java.net.URL.<init>(URL.java:432) ~[na:1.8.0_45]
    at com.fasterxml.jackson.databind.deser.std.FromStringDeserializer$Std._deserialize(FromStringDeserializer.java:212) ~[jackson-databind-2.6.2.jar:2.6.2]
    at com.fasterxml.jackson.databind.deser.std.FromStringDeserializer.deserialize(FromStringDeserializer.java:122) ~[jackson-databind-2.6.2.jar:2.6.2]
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:520) ~[jackson-databind-2.6.2.jar:2.6.2]
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:95) ~[jackson-databind-2.6.2.jar:2.6.2]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:337) ~[jackson-databind-2.6.2.jar:2.6.2]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:131) ~[jackson-databind-2.6.2.jar:2.6.2]
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:245) ~[jackson-databind-2.6.2.jar:2.6.2]

Pojo:

class foo {
   ...
   URL url
   ...
}

As the error says, is missing the protocol, how can insert the protocol before deserialize if it isn't set by the user?

xedo
  • 1,117
  • 3
  • 18
  • 34

4 Answers4

2

I made a combination of two previous answers:

public class Foo {
   ...
   @JsonDeserialize(using = UrlDeseralizer.class)
   private URL url;
   ...
}

public class UrlDeseralizer extends JsonDeserializer<URL> {

    private Pattern urlPrefix = Pattern.compile("^(https?://|ftp://).*");

    @Override
    public URL deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        ObjectCodec objectCodec = p.getCodec();
        JsonNode node = objectCodec.readTree(p);
        String stringUrl = node.asText();
        if (!urlPrefix.matcher(stringUrl).matches()) {
            return new URL("http://" + stringUrl);
        } else {
            return new URL(stringUrl);
        }
    }

}
xedo
  • 1,117
  • 3
  • 18
  • 34
1

You can use a custom deserializer Refer here for custome deserializer usage Custom JSON Deserialization with Jackson

Community
  • 1
  • 1
Senthil
  • 11
  • 2
  • looks good, but do I have to set all the parameters?(my class have around 20) can't filter just the URL one to be more reusable? – xedo Nov 04 '15 at 14:08
  • 1
    you can mark the URL field alone for the deserialization @JsonDeserialize( using=) private URL url; – Senthil Nov 04 '15 at 15:07
1

You can use a custom deserializer (see the other answer). Another solution - not so elegant, but straightforward - is to create a setter in your bean that accepts String values and do some preparation inside before creating a URL object:

private Pattern urlPrefix = Pattern.compile("^(https?://|ftp://).*"); //etc.
//...
public void setUrl(String url) {
    if (url != null && urlPrefix.matcher(url).matches()) {
        this.url = new URL(url);
    } else {
        this.url = new URL("http://" + url);
    }
}
pkalinow
  • 1,619
  • 1
  • 17
  • 43
0

@xedo helped me (thanks!), but to be a bit safer you should catch all MalformedURLExceptions:

public class Foo {
   ...
   @JsonDeserialize(using = UrlDeseralizer.class)
   private URL url;
   ...
}

public class UrlDeseralizer extends JsonDeserializer<URL> {

    private Pattern urlPrefix = Pattern.compile("^(https?://|ftp://).*");

    @Override
    public URL deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        ObjectCodec objectCodec = p.getCodec();
        JsonNode node = objectCodec.readTree(p);
        String stringUrl = node.asText();
        try {
            return new URL(stringUrl);
        } catch (MalformedURLException e) {
            // log.debug("Malformed URL: ‘" + stringUrl + "’", e);
            return null;
        }
    }
}
Grant
  • 1,124
  • 8
  • 9