stwissel
stwissel

Reputation: 20384

How deserialize plain String to Json using Jackson in Java?

I have a simple class as property of mage:

// getter/setter omitted for brevity
public class Magic() {
  String Spell;
  int strength;
}

public class Mage() {
  String name;
  Magic magic;
}

I need to deserialize JSON from 2 different source strings:

{
  "name" : "Sauron",
  "magic" : {
        "spell" : "Tamador",
        "strenght" : 10
   }
}

and

{
  "name" : "Gandalf",
  "magic" : "You shall not pass"
}

or even "You shall not pass" -> Magic object

I thought going with @JsonDeserialize(using = MagicDeserializer.class) would be the way to go with Jackson, but the Parser barfs with "Unrecognized token". Is there a way I can intercept the loading to do my own parsing?

Upvotes: 0

Views: 875

Answers (1)

dariosicily
dariosicily

Reputation: 4582

The idea of a custom deserializer is correct, you can extends the StdDeserializer class and in its deserialize method convert the json to a JsonNode separating the two Stringand Object distinct values associated to the magic key in the json:

public class MagicDeserializer extends StdDeserializer<Magic> {

    public MagicDeserializer() {
        super(Magic.class);
    }

    @Override
    public Magic deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException {
        final ObjectCodec codec = jp.getCodec();
        JsonNode root = codec.readTree(jp);
        Magic magic = new Magic();
        if (root.isTextual()) { //<- magic is a string
            magic.setSpell(root.textValue());
            return magic;
        }
        //ok, so magic is an Magic object
        return codec.treeToValue(root, Magic.class);
    }
}

Then if you annotate your Magic field you can deserialize both the jsons:

@Data
public class Mage {

    private String name;
    @JsonDeserialize(using = MagicDeserializer.class)
    private Magic magic;
}

@Data
public class Magic {

    private String Spell;
    private int strength;
}

Mage sauron = mapper.readValue(json1, Mage.class);
System.out.println(mapper.writeValueAsString(sauron));
Mage gandalf = mapper.readValue(json2, Mage.class);
System.out.println(mapper.writeValueAsString(gandalf));

Upvotes: 2

Related Questions