Specify field is transient for MongoDB but not for RestController
As long as you use org.springframework.data.annotation.Transient
it should work as expected. Jackson knows nothing about spring-data and it ignores it's annotations.
Sample code, that works:
interface PersonRepository extends CrudRepository<Person, String> {}
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.mapping.Document;
@Document
class Person {
@Id
private String id;
private String name;
@Transient
private Integer age;
// setters & getters & toString()
}
@RestController
@RequestMapping("/person")
class PersonController {
private static final Logger LOG = LoggerFactory.getLogger(PersonController.class);
private final PersonRepository personRepository;
@Autowired
PersonController(PersonRepository personRepository) {
this.personRepository = personRepository;
}
@RequestMapping(method = RequestMethod.POST)
public void post(@RequestBody Person person) {
// logging to show that json deserialization works
LOG.info("Saving person: {}", person);
personRepository.save(person);
}
@RequestMapping(method = RequestMethod.GET)
public Iterable<Person> list() {
Iterable<Person> list = personRepository.findAll();
// setting age to show that json serialization works
list.forEach(foobar -> foobar.setAge(18));
return list;
}
}
Executing POST http://localhost:8080/person
:
{
"name":"John Doe",
"age": 40
}
- Log output
Saving person: Person{age=40, id='null', name='John Doe'}
- Entry in
person
collection:{ "_id" : ObjectId("55886dae5ca42c52f22a9af3"), "_class" : "demo.Person", "name" : "John Doe" }
- age is not persisted
Executing GET http://localhost:8080/person
:
- Result:
[{"id":"55886dae5ca42c52f22a9af3","name":"John Doe","age":18}]
I solved by using @JsonSerialize. Optionally you can also opt for @JsonDeserialize if you want this to be deserailized as well.
@Entity
public class Article {
@Column(name = "title")
private String title;
@Transient
@JsonSerialize
@JsonDeserialize
private Boolean testing;
}
// No annotations needed here
public Boolean getTesting() {
return testing;
}
public void setTesting(Boolean testing) {
this.testing = testing;
}
The problem for you seems to be that both mongo and jackson are behaving as expected. Mongo does not persist the data and jackson ignores the property since it is marked as transient. I managed to get this working by 'tricking' jackson to ignore the transient field and then annotating the getter method with @JsonProperty
. Here is my sample bean.
@Entity
public class User {
@Id
private Integer id;
@Column
private String username;
@JsonIgnore
@Transient
private String password;
@JsonProperty("password")
public String getPassword() {
return // your logic here;
}
}
This is more of a work around than a proper solution so I am not sure if this will introduce any side effects for you.