Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I have a class like this:

public class DeserializedHeader
    int typeToClassId;
    Object obj

I know what type of object obj is based on the typeToClassId, which is unfortunately only known at runtime.

I want to parse obj out based on typeToClassId - what's the best approach here? Annotations seem like they're out, and something based on ObjectMapper seems right, but I'm having trouble figuring out what the best approach is likely to be.

Something along the lines of Class clazz = lookUpClassBasedOnId(typeToClassId) objectMapper.readValue(obj, clazz)

Obviously, this doesn't work since obj is already deserialized... but could I do this in 2 steps somehow, perhaps with convertValue?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
144 views
Welcome To Ask or Share your Answers For Others

1 Answer

This is really complex and painful problem. I do not know any sophisticated and elegant solution, but I can share with you my idea which I developed. I have created example program which help me to show you how you can solve your problem. At the beginning I have created two simple POJO classes:

class Product {

    private String name;

        // getters/setters/toString
}

and

class Entity {

    private long id;

    // getters/setters/toString
}

Example input JSON for those classes could look like this. For Product class:

{
  "typeToClassId" : 33,
  "obj" : {
    "name" : "Computer"
  }
}

and for Entity class:

{
  "typeToClassId" : 45,
  "obj" : {
    "id" : 10
  }
}

The main functionality which we want to use is "partial serializing/deserializing". To do this we will enable FAIL_ON_UNKNOWN_PROPERTIES feature on ObjectMapper. Now we have to create two classes which define typeToClassId and obj properties.

class HeaderType {

    private int typeToClassId;

    public int getTypeToClassId() {
        return typeToClassId;
    }

    public void setTypeToClassId(int typeToClassId) {
        this.typeToClassId = typeToClassId;
    }

    @Override
    public String toString() {
        return "HeaderType [typeToClassId=" + typeToClassId + "]";
    }
}

class HeaderObject<T> {

    private T obj;

    public T getObj() {
        return obj;
    }

    public void setObj(T obj) {
        this.obj = obj;
    }

    @Override
    public String toString() {
        return "HeaderObject [obj=" + obj + "]";
    }
}

And, finally source code which can parse JSON:

// Simple binding
Map<Integer, Class<?>> classResolverMap = new HashMap<Integer, Class<?>>();
classResolverMap.put(33, Product.class);
classResolverMap.put(45, Entity.class);

ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

String json = "{...}";

// Parse type
HeaderType headerType = mapper.readValue(json, HeaderType.class);
// Retrieve class by integer value
Class<?> clazz = classResolverMap.get(headerType.getTypeToClassId());
// Create dynamic type
JavaType type = mapper.getTypeFactory().constructParametricType(HeaderObject.class, clazz);
// Parse object
HeaderObject<?> headerObject = (HeaderObject<?>) mapper.readValue(json, type);
// Get the object
Object result = headerObject.getObj();

System.out.println(result);

Helpful links:

  1. How To Convert Java Map To / From JSON (Jackson).
  2. java jackson parse object containing a generic type object.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...