4

I am using SpringBoot with Mongo database and I am trying to save embedded documents into database.

I have this model:

Profile.java

@Data
@Document
public class Profile {

    public final City city;
    public final String imageId;

    public Profile(City city,
                   String imageId) {
        this.city = city;
        this.imageId = imageId;
    }

    @Override
    public String toString() {
        return "Profile{" +
                ", city=" + city +
                ", imageId='" + imageId + '\'' +
                '}';
    }

    private static boolean atLeast(int numChars, String s) {
        if (s == null) {
            return false;
        }
        var str = s.strip();
        return str.length() >= numChars;
    }


    public static ProfileBuilder builder() {
        return new ProfileBuilder();
    }

    public static final class ProfileBuilder {
        public City city;
        public String imageId;

        private ProfileBuilder() {
        }


        public ProfileBuilder withCity(City city) {
            this.city = city;
            return this;
        }

        public ProfileBuilder withImageId(String imageId) {
            this.imageId = imageId;
            return this;
        }

        public Profile build(){
            return new Profile(city, imageId);
        }
    }
}

City.java

public class City {

    public final String name;

    public City(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "City{" +
                ", name='" + name + '\'' +
                '}';
    }
}

ProfileController.java

 @RequestMapping( method = RequestMethod.POST)
    public Profile addUser(@RequestBody Profile profile) {
        return profileService.addProfile(profile);
    }

and with postman I am sending this JSON

{
 "city":{
   "name":"Atena"
  },
   "imageId" : "Doe",
  }
}

But I am getting following error:

"JSON parse error: Cannot construct instance of `domain.City` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator);"
2
  • Please add the code of your REST Controller where you receive this JSON Commented Oct 12, 2021 at 9:34
  • I added it, you can take a look :) Commented Oct 12, 2021 at 9:39

2 Answers 2

11

In classes with only one attribute, to deserialize an object Json need a nos argument constructor from that class.

In your class city you need a nos arg constructor add this to your class you need:

 public  City () {}
Sign up to request clarification or add additional context in comments.

1 Comment

Could you please tell me why no-argument constructor is required for classes with only one property, but not for classes with more than one field? Even after reading this article(stackoverflow.com/questions/64080983/…), I still don't understand.
9

There are at least two solutions.

  1. Add @JsonCreator to constructor and @JsonProperty to its arguments (to instruct Jackson how to substitute JSON items into constructor in proper order)
class Profile {
    ...
    @JsonCreator
    public Profile(@JsonProperty("city") City city, 
                   @JsonProperty("imageId") String imageId) {
        this.city = city;
        this.imageId = imageId;
    }
    ...
}

(+ same for City class)

  1. Unfinal class properties and provide default no-arg constructor (along with existing all-arg constructor).
class Profile {

    public City city;
    public String imageId;

    public Profile() {
    }

    public Profile(City city, String imageId) {
        this.city = city;
        this.imageId = imageId;
    }
}

(+ same for City class)

Test

class Test {
    public static void main(String[] args) throws JsonProcessingException {
        String json = "{\"city\":{\"name\":\"Atena\"},\"imageId\":\"Doe\"}";
        Profile p = new ObjectMapper().readValue(json, Profile.class);
        System.out.println(p);
    }
}

Output:

Profile{, city=City{, name='Atena'}, imageId='Doe'}

7 Comments

I am having same error for first example you provided and for second it has to be final. So I have to find way of making it work with final
It works for me. I've updated my answer with unit test. PS: Make sure that you use valid JSON, because one that you've shown in your Question is invalid
Yes, I wrote test for it as well and it works fine, but when I am sending it with postman as JSON it's not working. Hmm maybe you are right my JSON is wrong. Can you please help with working one?
@user9347049 in my test snippet {"city":{"name":"Atena"},"imageId":"Doe"} is a valid JSON
Thank you for your help! :) it works now
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.