Omer
Omer

Reputation: 57

Java - Json string to Set<T>

I know there is a lot of content on this throughout the web but I couldn't find one that will help me solve this (been looking for about two days now...).

I have a json string which looks like this:

[
  {
    "firstName": "dan",
    "lastName": "cohen",
    "email": "[email protected]",
    "userName": "aaaddd",
    "password": "1cczzdddds",
    "agentCode": 0
  },
  {
    "firstName": "omer",
    "lastName": "sha",
    "email": "[email protected]",
    "userName": "asdf",
    "password": "asdf",
    "agentCode": 1
  }
]

I am trying to read this json into Set<T> since I am going to use this function in order to read json files to set of other types. E.g, here I am trying to read into Set<Agent> while later on I'll try to read another file into Set<Passenger>.

This is the function which reads the json file:

public Set<T> read() {
    try {
        return new ObjectMapper().readValue(new File(this.fileName), new TypeReference<Set<Agent>>(){});
    }

    /* Errors handling */
    } catch (IOException e) {
        e.printStackTrace();
    }

    return null;
}

The line Set<T> sample = new ObjectMapper().readValue(jsonString, new TypeReference<Set<Agent>>(){}); is responsible for deserialize the json string into a Set<Agent>.

But the moment I try to change it from:

Set<T> sample = new ObjectMapper().readValue(jsonString, new TypeReference<Set<Agent>>(){});

To:

Set<T> sample = new ObjectMapper().readValue(jsonString, new TypeReference<Set<T>>(){});

When trying to execute this code (which lies in the main function):

Set<Agent> agents = fileManagerAgent.read();
Iterator<Agent> it = agents.iterator();
while(it.hasNext()){
    System.out.println(it.next().getUserName());
}

I am getting an error saying:

Exception in thread "main" java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class model.objects.Agent (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; model.objects.Agent is in unnamed module of loader 'app')

From what I have read, this happens because in run-time, something happens to T and the compiler addresses it as Object and so, it is deserializing the json into a LinkedHashMap.

Once it does that, I cannot access the Agent object inside the set.

This is what calls the function to read from a json file into Set<T> (which is also in the main function):

FileManager<Agent> fileManagerAgent = new FileManager<>("src/data/agents.json");
Set<Agent> agents = fileManagerAgent.read();

Also, this code is written using Jackson.

Any ideas on how to solve this?

If any more information is needed please inform me and I will update the question.

Upvotes: 2

Views: 3044

Answers (2)

magicmn
magicmn

Reputation: 1914

Add the Class you want as parameter. In this example the passed Class has to be Agent.class for a FileManager<Agent>.

public Set<T> read(Class<T> clazz) {
    try {
        ObjectMapper = mapper = new ObjectMapper();
        return mapper.readValue(new File(fileName), mapper.getTypeFactory().constructCollectionType(Set.class, clazz));
    } catch (IOException e) {
        // Exception handling
    }
}

And then use it like this: Set<Agent> agents = new FileManager<>("agent.json").read(Agent.class);

or pass the class when you create youre file manager

public class FileManager<T> {

    private String fileName;
    private Class<T> clazz;

    public Set<T> read() {
        // Same code.
    }
}

Now the code would change to: Set<Agent> agents = new FileManager<>("agent.json", Agent.class).read();

Upvotes: 3

Jaykumar Javiya
Jaykumar Javiya

Reputation: 67

Create VO class which is equivalent to your input file, pass this class to ObjectMapper.

new ObjectMapper().readValue(new File(this.fileName), Object of JsonSetVo);

public class JsonSetVo<T> {

    Set<T> inputSet;

    public Set<T> getInputSet() {
        return inputSet;
    }

    public void setInputSet(Set<T> inputSet) {
        this.inputSet = inputSet;
    }
}

Upvotes: -1

Related Questions