Spring Data Mongo + Lazy Load + REST Jackson

Hello I have some problems with Spring and Mongo with Lazy Load.

I have this configuration:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.1.RELEASE</version>
</parent>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

      

This document:

@Document
public class User {
    @Id
    private String id;

    @DBRef
    private Place place;

    @DBRef(lazy=true)
    private Country country;

    .
    .
    .
}

      

Everything works fine, but when I expose "User" in RestController like:

@RestController
public class UserController {

    .
    .
    .

    @RequestMapping(value = "user/{idUser}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public User getById(@PathVariable("idUser") String idUser){    
            return userService.getById(idUser);    
    }
}

      

Output:

  {
    "id": "58ebf11ee68f2751f33ae603",
    "place": {
      "id": "58e3bf76e76877586435f5af",
      "name": "Place X"
    },
    "country": {
      "id": "58daa782e96139070bbc851c",
      "name": "MΓ©xico",
      "target":{
        "id": "58daa782e96139070bbc851c",
        "name": "MΓ©xico",
      }
    }
  }

      

Questions:

  • If "country" is marked as "lazy = true" why is it printed?

  • Why does "country" have a new "target" field?

  • How can I avoid serializing fields marked as "lazy = true"?

in advance for your help.

+3


source to share


1 answer


I had a similar problem with the "target" exponent in the serialized results and was able to solve this problem by creating my own serializer so that it serializes the actual object and not a proxy that has a "target" field and is named funky- class.

Obviously, you could choose not to select the target, but simply to fetch and serialize it, as shown here:

public class DBRefSerializer extends JsonSerializer<Object> {

    @Override
    public void serialize(Object value, JsonGenerator generator, SerializerProvider provider)
            throws JsonGenerationException, IOException {

        provider.defaultSerializeValue(value, generator);
    }

    @Override
    public void serializeWithType(Object value, JsonGenerator generator, SerializerProvider provider,
            TypeSerializer typeSer)
            throws IOException {

        Object target = value;
        if (value instanceof LazyLoadingProxy) {
            LazyLoadingProxy proxy = (LazyLoadingProxy)value;
            target = proxy.getTarget();
            provider.defaultSerializeValue(target, generator);
        } else {
            provider.defaultSerializeValue(target, generator);
        }
    }
}

      



And then annotate the DBRefs you want to run through it like this:

@JsonSerialize(using=DBRefSerializer.class)
@DBRef(lazy = true)
private SomeClass someProperty;

      

Obviously this is not ideal for everyone, but I figured I would post it in case it helps someone else.

0


source







All Articles