5

Here are the entity classes for my project

import java.util.Iterator;
import java.util.Map;
import java.util.Set;

@Entity
@Table(name="training")
public class Training {

    @Id
    @GeneratedValue
    private long id;
    
    private String topic;
    
    
    @OneToMany(mappedBy="training")     
    private Set<Session> sessions = new HashSet<Session>();
    
    public Training(){
        
    }
    
    public Training(String topic, TransitionLevel level, Set<Session> sessions) {
        this.topic = topic;
        this.level = level;
        this.sessions = sessions;
    }


    public long getId() {
        return id;
    }


    public void setId(long id) {
        this.id = id;
    }


    public String getTopic() {
        return topic;
    }


    public void setTopic(String topic) {
        this.topic = topic;
    }


    public Set<Session> getSessions() {
        return sessions;
    }


    public void setSessions(Set<Session> sessions) {
        this.sessions = sessions;
    }
    
}

Here is the Session Table

    @Entity
    @Table(name="session")
    public class Session {
    
        @Id
        @GeneratedValue
        private long id;
        
        private String location;
        
        @ManyToOne  
        @JoinColumn(name="training_id") 
        @JsonIgnore
        private Training training;
        
        private Date start;
        
        private Date end;
        
        
        @JoinTable(name="session_user",
                joinColumns = @JoinColumn(name="session_id"),
                inverseJoinColumns = @JoinColumn(name="trainingRole_id"))
        @MapKeyJoinColumn(name="user_id")
        @ElementCollection  
        @JsonIgnore
        

    private Map&lt;User, TrainingRole&gt; users = new HashMap&lt;User, TrainingRole&gt;();</div>
        
        public long getId() {
            return id;
        }
    
    
        public void setId(long id) {
            this.id = id;
        }
    
    
        public String getLocation() {
            return location;
        }
    
    
        public void setLocation(String location) {
            this.location = location;
        }
    
    
        public Training getTraining() {
            return training;
        }
    
    
        public void setTraining(Training training) {
            this.training = training;
        }
    
    
        public Date getStart() {
            return start;
        }
    
    
        public void setStart(Date start) {
            this.start = start;
        }
    
    
        public Date getEnd() {
            return end;
        }
    
    
        public void setEnd(Date end) {
            this.end = end;
        }
    
    
        public Map &lt;User, TrainingRole&gt; getUsers() {
            return users;
        }
    
    
        public void setUsers(Map&lt;User, TrainingRole&gt; users) {
            this.users = users;
        }
            
    }

Here is the User Entity

@Entity
@Table(name="user")
public class User {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="id")
    private long id;
    
    @Column(name="csl",unique=true)
    private String csl;
    
    @Column(name="fullName")
    private String fullName;
    
    
    @Column(name="email")
    private String email;       
    
    public User() {

    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }


    public String getCsl() {
        return csl;
    }


    public void setCsl(String csl) {
        this.csl = csl;
    }


    public String getFullName() {
        return fullName;
    }


    public void setFullName(String fullName) {
        this.fullName = fullName;
    }

}

I am using JPARepository to save training and session objects in my mysql database

But Whenever I am saving the training object or session object

I am getting the error

c.j.MappingJackson2HttpMessageConverter : Failed to evaluate Jackson deserialization for type [simple type, class Session]: com.fasterxml.jackson.databind.JsonMappingException: Can not find a (Map) Key deserializer for type [simple type, class User]

I googled it and found I need to serialize and deserialize manually, but I have no idea how to do that

eglease
  • 2,445
  • 11
  • 18
  • 28

1 Answers1

3

To use your own classes as keys for maps you need a serializer and deserializer, like you indicate. Something like:

public class CustomKeyDeserializer extends KeyDeserializer {

    private static ObjectMapper mapper = new ObjectMapper();

    @Override
    public Object deserializeKey(String key, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
        return mapper.readValue(key, User.class);
    }
}

public class CustomKeySerializer extends JsonSerializer<User> {

    private static ObjectMapper mapper = new ObjectMapper();

    @Override
    public void serialize(User value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
        gen.writeFieldName(mapper.writeValueAsString(value));
    }
}

And also annotate the field

    @JsonDeserialize(keyUsing = CustomKeyDeserializer.class)
    @JsonSerialize(keyUsing = CustomKeySerializer.class)
    private Map<User, TrainingRole> users = new HashMap<User, TrainingRole>();
Franjavi
  • 647
  • 4
  • 14
  • Hey Man .. this worked .. Now the error is gone and JSON also got formed .. but do you have any idea how to remove the back slashes .. the generated JSON is like this "users":{"{\"id\":1,\"csl\":\"admin\",\"fullName\":\"admin\",\" .. . ... . .. .. –  Sep 12 '16 at 11:32
  • I don't think you can. What the key serializer does is create a string from the object, because json only works with strings as map keys. If you remove the back slashes you will have a malformed json. A second option is to change the key to a string. – Franjavi Sep 12 '16 at 12:11