Hello.

I have a custom collection type that, for the purposes of this question,
acts mostly like a Map<String, ?> (the real type has extra invariants to
preserve, but they're not relevant here). The container is heterogeneous
in that the values are not required to have the same type, nor be
subtypes of a single type.

The problem I'm having is that I can't come up with a deserializer that
can cope with it.

For example: In the application, I have some custom vector (in the
mathematical sense) types. An implementation of
StdDeserializer<Vector2> for those types looks like:

    final JsonNode cons = node.get("Vector2");
    if (cons instanceof ObjectNode) {
      final double x = cons.get("x").doubleValue();
      final double y = cons.get("y").doubleValue();
      return new Vector2(x, y);
    }
    throw new JsonParseException(jp, "Expected a Vector2 constructor");

This would parse json of the following form:

  {
    "Vector2": {
      "x": 1.0,
      "y": 2.0
    }
  }

This works correctly when I can actually tell Jackson that what it's
parsing should be parsed as if it were a Vector2. However, if Jackson
encounters a "Vector2" key somewhere in a structure, it's obviously not
going to know that that field is supposed to be parsed as a Vector2.

So, if I treat my map-like structure as if it were a plain Java Map<>
and let Jackson parse it, any "Vector2" objects will be parsed as
nested hash maps instead of Vector2 values, and that's obviously no
good.

Unless there's a better way, I need to write a custom deserializer for
the map type that knows how to recognize Vector2 typed values.
Something like this:

  @Override
  public DictionaryType deserialize(
    final JsonParser jp,
    final DeserializationContext ctxt)
    throws IOException, JsonProcessingException
  {
    final DictionaryType dictionary = Dictionary.create();

    final ObjectCodec codec = jp.getCodec();
    final TreeNode node = codec.readTree(jp);
    final Iterator<String> iter = node.fieldNames();
    while (iter.hasNext()) {
      final String key = iter.next();
      final JsonNode value = (JsonNode) node.get(key);
      if (value.get("Vector2") != null) {
        dictionary.put(key,
        Vector2Deserializer.parseVector2(jp, value));
        continue;
      }

      // XXX: ?!
    }

    return dictionary;
  }

There are multiple problems with this. One is that I feel like I
shouldn't be having to do this at all. Is there some way I can tell
Jackson about Vector2 fields in arbitrary collections? Failing that,
how do I replace the // XXX ?! with code that falls back to having
Jackson parse other values in whatever manner it would have done
otherwise? In other words, using whatever other deserializers I have
registered in the current module, etc.

Any help would be appreciated.

M

-- 
You received this message because you are subscribed to the Google Groups 
"jackson-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
For more options, visit https://groups.google.com/d/optout.

Attachment: pgpIPWSy396Hr.pgp
Description: OpenPGP digital signature

Reply via email to