建造者模式在使用Jackson反序列化时不起作用。

huangapple go评论62阅读模式
英文:

Builder pattern deserialize with jackson not working

问题

我试图处理请求

{
  "city": "city",
  "date": "2020-08-26T12:15:54.428Z",
  "time": {
      "sum":"123"
  }
}

我的目标是处理这个请求。关键在于,我尝试使用Builder模式处理可选参数(根据Effective Java,Joshua Bloch)。据我理解,我不必发送所有时间值。只有sum是必需的。我尝试通过Postman将Sport对象发送到我的控制器的RequestBody。

因此,我为我的Sport创建了POJO类:

@Entity
@Table(name = "sport")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Sport {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "date")
    private Date date;

    @Column(name = "city")
    private City city;

    @Type(type = "time")
    private Time time;
}

和Time构建器:

package pl.project.model;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;

@JsonDeserialize(builder = Time.Builder.class)
public class Time {
    private final String bike;
    private final String run;
    private final String sum;

    private Time(Builder builder) {
        bike = builder.bike;
        run = builder.run;
        sum = builder.sum;

    }

    @JsonPOJOBuilder(withPrefix = "")
    public static class Builder {

        String bike = "-";
        String run = "-";
        final String sum;

        Builder(String sum) {
            this.sum = sum;
        }

        Builder bike(String bike) {
            this.bike = bike;
            return this;
        }

        Builder run(String run) {
            this.run = run;
            return this;
        }

        Time build() {
            return new Time(this);
        }

    }
}

仍然遇到错误:

JSON parse error: Cannot construct instance of `pl.project.model.Time$Builder` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `pl.project.model.Time$Builder` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator) at [Source: (PushbackInputStream); line: 14, column: 7] (through reference chain: pl.project.model.Sport["time"])

我尝试了许多stackoverflow上的解决方案,但对我都没有用。有人可以帮助我吗?

英文:

I try to handle request

{
  "city": "city",
  "date": "2020-08-26T12:15:54.428Z",
  "time": {
      "sum":"123"
  }
}

My goal is to process this request. The trick is that I try to use Builder pattern with optional parameter(according to Effective Java. Joshua Bloch). As I understand I dont have to send all time values. Only sum is required.
I try to send Sport object in my RequestBody to my controller by Postman.

So I created POJO class for my Sport:

@Entity
@Table(name = "sport")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Sport {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "date")
    private Date date;

    @Column(name = "city")
    private City city;

    @Type(type = "time")
    private Time time;
}

and
Time builder:

package pl.project.model;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;

@JsonDeserialize(builder = Time.Builder.class)
public class Time {
    private final String bike;
    private final String run;
    private final String sum;

    private Time(Builder builder) {
        bike = builder.bike;
        run = builder.run;
        sum = builder.sum;

    }

    @JsonPOJOBuilder(withPrefix = "")
    public static class Builder {

        String bike = "-";
        String run = "-";
        final String sum;

        Builder(String sum) {
            this.sum = sum;
        }

        Builder bike(String bike) {
            this.bike = bike;
            return this;
        }

        Builder run(String run) {
            this.run = run;
            return this;
        }

        Time build() {
            return new Time(this);
        }

    }
}

And still getting error:

JSON parse error: Cannot construct instance of `pl.project.model.Time$Builder` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `pl.project.model.Time$Builder` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)\n at [Source: (PushbackInputStream); line: 14, column: 7] (through reference chain: pl.project.model.Sport[\"time\"])"

I tried many stackoverflow solutions but nothing works for me.

Does anybody could help me?

答案1

得分: 3

@JsonPOJOBuilder(withPrefix = "")
public static class Builder {
    String bike = "-";
    String run = "-";
    final String sum;

    Builder(@JsonProperty("sum") String sum) {
        this.sum = sum;
    }

    Builder bike(String bike) {
        this.bike = bike;
        return this;
    }

    Builder run(String run) {
        this.run = run;
        return this;
    }

    Time build() {
        return new Time(this);
    }
}
@JsonPOJOBuilder(withPrefix = "")
public static class Builder {
    String bike = "-";
    String run = "-";
    String sum;

    Builder sum(String sum) {
        this.sum = sum;
        return this;
    }

    @JsonProperty("bike") // must explicitly name for non-standard method name
    Builder setBicycle(String bike) {
        this.bike = bike;
        return this;
    }

    Builder run(String run) {
        this.run = run;
        return this;
    }

    Time build() {
        if (this.sum == null) // need to validate here, since property is otherwise optional
            throw new IllegalStateException("Required property missing: sum");
        return new Time(this);
    }
}
英文:

The Builder class has to have methods named after the property, and/or use @JsonProperty to name the values.

Using @JsonProperty for constructor parameters

@JsonPOJOBuilder(withPrefix = "")
public static class Builder {
	String bike = "-";
	String run = "-";
	final String sum;
	
	Builder(@JsonProperty("sum") String sum) { // must explicitly name the property
		this.sum = sum;
	}
	
	Builder bike(String bike) {
		this.bike = bike;
		return this;
	}
	
	Builder run(String run) {
		this.run = run;
		return this;
	}
	
	Time build() {
		return new Time(this);
	}
}

Using builder "setter" method

@JsonPOJOBuilder(withPrefix = "")
public static class Builder {
	String bike = "-";
	String run = "-";
	String sum;
	
	Builder sum(String sum) { // standard builder "setter" method
		this.sum = sum;
		return this;
	}
	
	@JsonProperty("bike") // must explicitly name for non-standard method name
	Builder setBicycle(String bike) {
		this.bike = bike;
		return this;
	}
	
	Builder run(String run) {
		this.run = run;
		return this;
	}
	
	Time build() {
		if (this.sum == null) // need to validate here, since property is otherwise optional
			throw new IllegalStateException("Required property missing: sum");
		return new Time(this);
	}
}

huangapple
  • 本文由 发表于 2020年8月31日 21:24:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/63671693.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定