2016-08-11 3 views
1

Kürzlich habe ich einen neuen Job angefangen (4 Monate) und ich habe noch viel von Spring zu lernen. Eines der Probleme, die wir haben, ist, dass, wenn wir Objekte aus der DB bringen und sie in ein Repository (JSON) einbinden (JSON), eine Menge unnötiger Daten - zum Beispiel (kleines Beispiel):JSON Object mapping - Spring Data

Wir haben eine Klasse Employee, die eine Abteilung Objekt hat und es bringt die folgenden:

{ 
    'EmployeeId':1, 
    'Name':'John', 
    'Email':'[email protected]' 
    'Department': { 
      'DepartmentId':1, 
      'name':'Development', 
      'location':'Somewhere', 
    } 
} 

Klasse Details:

@Entity 
@Table(name = "Employees") 
@NamedQuery(name = "Employee.findAll", query = "SELECT e FROM Employees e") 
public class Employee implements Serializable { 
private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name = "EmployeeId") 
    private long EmployeeId; 

    @Column(name = "Email") 
    private String email; 

    @Column(name = "address") 
    private String address; 

    @ManyToOne 
    @JoinColumn(name = "DepartmentId") 
    @JsonBackReference(value = "department_employee") 
    private Departament departament; 

    // Other attributes, setters & getters 

} 

Wenn ich einen „custom“ Mapper zu bauen, die die beste ist trainieren? Oder wie kann ich etwas implementieren, die mir erlaubt, eine JSON zu erstellen, die mir so etwas wie dies bringt:

{ 
    'EmployeeId':'1', 
    'Name':'John', 
    'Email':'[email protected]' 
} 

Ich habe einige der Forschung getan, und ich stolperte über die folgenden Beispiele:

Jackson JSON Views

Jackson's @JsonView, @JsonFilter and Spring

auch denke ich habe für ein bestimmten ein generisches Objekt zu verwenden, die ein HashMap enthält, so kann ich schließen, auf dem Controller die Daten, die wir wollen oder müssen Bildschirm.

Ich schätze wirklich jede Hilfe - hoffe, die Frage ist klar genug.

+0

btw nach, Frage auch auf gepostet: https: // coderanch.com/t/669152/Spring/Spring-Mapping-Objects#3124303 –

+0

Wenn Sie die Abteilung nicht serialisieren möchten, können Sie die Annotation @JsonIgnoreProperties verwenden. – Azizi

+0

Ich entschuldige mich, wenn ich das in der Frage nicht angegeben habe - auf einigen Bildschirmen brauche ich die Abteilung, zum Beispiel wenn ich den Mitarbeiter aktualisieren muss.Aber, wenn ich nur den Namen, die E-Mail und einige spezifische Daten anzeigen muss, was ist der angemessenste Weg, dies zu tun? Die @ JsonIgnoreProperties ignoriert das Feld vollständig. –

Antwort

1

Eine Bibliothek, die besonders gut für mich funktioniert, ist Model Mapper. Die Art, wie ich es benutze ist, indem ich dein Domain-Objekt (wie du es jetzt tust) und ein DTO habe. In Ihrem Fall also Employee und EmployeeDTO. Dies ermöglicht eine klare Trennung zwischen den Schichten Ihrer App, und die Zuordnung zwischen Mitarbeiter und Mitarbeiter mit dem Model Mapper ist ziemlich einfach, nur modelMapper(employee, EmployeeDTO.class) zum Beispiel. Alles, was Sie für die einfachen Fälle tun müssen, ist, dass Sie die Eigenschaften mit demselben Namen in der Domänenklasse und der DTO-Klasse benennen, und die Bibliothek wird dafür sorgen, dass die Werte kopiert werden. Für kompliziertere Fälle gibt es mehrere Alternativen, die Ihren Code noch sauber machen.

+0

Danke @Ulises Ich werde es versuchen und sehen, wie es funktioniert. –

0

Sagen Sie zum Beispiel haben Sie eine JPA-Entität Kommentar (die der Benutzer macht einen Kommentar erfasst), und Sie wollten die Serialisierung (Umwandlung von Objekt -> JSON) anpassen

Definieren Sie die Einheit

//Comment Entity Attributes (This is just an example make sure you properly annotate the entity etc...): 
private String id; 
private final String userId; 
private String discussionId; 
private final Date createdTime; 
private final String comment; 

erstellen eines benutzerdefinierten Serializer

/*Serializer*/ 
import org.springframework.stereotype.Component; 
import com.fasterxml.jackson.core.JsonGenerator; 
import com.fasterxml.jackson.core.JsonProcessingException; 
import com.fasterxml.jackson.databind.JsonSerializer; 
import com.fasterxml.jackson.databind.SerializerProvider; 

@Component 
@Slf4j 
public class CommentSerializer extends JsonSerializer<Comment> { 


    @Override 
    public void serialize(Comment comment, JsonGenerator jgen, SerializerProvider provider) 
      throws IOException, 
      JsonProcessingException { 
     jgen.writeStartObject(); 
     jgen.writeStringField("id", comment.getId()); 
     jgen.writeStringField("userId", comment.getUserId()); 
     jgen.writeStringField("firstName", redisRepo.getName(comment.getUserId(), false)); 
     jgen.writeStringField("discussionId", comment.getDiscussionId()); 
     jgen.writeStringField("createdTime", String.valueOf(comment.getCreatedTime().getTime())); 
     jgen.writeStringField("comment", comment.getComment()); 
     jgen.writeEndObject(); 
    } 


} 

konfigurieren Sie den Serializer

/*Config*/ 
import org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean; 
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; 
import org.springframework.boot.autoconfigure.web.HttpMessageConverters; 

@Autowired 
private CommentSerializer commentSerializer; 

@Bean 
public HttpMessageConverters httpMessageConverters() { 
    return new HttpMessageConverters(mappingJackson2HttpMessageConverter()); 
} 

    @Bean 
    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { 
     MappingJackson2HttpMessageConverter mappingJackson2JsonView = new MappingJackson2HttpMessageConverter(); 
     mappingJackson2JsonView.setObjectMapper(objectMapper()); 
     return mappingJackson2JsonView; 
    } 


    @Bean 
    public ObjectMapper objectMapper() { 



     Map<Class<?>, JsonSerializer<?>> serializerMap = new HashMap<>(); 
     serializerMap.put(Comment.class, commentSerializer); 

     Jackson2ObjectMapperFactoryBean objectMapperFactoryBean = new Jackson2ObjectMapperFactoryBean(); 
     objectMapperFactoryBean.setIndentOutput(true); 

     objectMapperFactoryBean.setSerializersByType(serializerMap); 
     objectMapperFactoryBean.afterPropertiesSet(); 

     ObjectMapper objectMapper = objectMapperFactoryBean.getObject(); 
     objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); 
     objectMapper.findAndRegisterModules(); 
     objectMapper.addMixInAnnotations(OAuth2Exception.class, OAuth2ExceptionMixin.class); 

     return objectMapper; 
    } 

Nun, wenn der entsprechende URL/Endpunkt genannt wird (wie unten) ist es immer serialisiert wird die Logik definiert im CommentSerializer)

@RequestMapping(value = "/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) 
public Comment findOne(@PathVariable("id") String id) 
     .... 
    return comment; 
}