Spring 乌马尔沙林-蒙斯代斯普林杰克逊酒店
正在尝试创建restful服务以保存“PeriodeSeignment”,如下所示:Spring 乌马尔沙林-蒙斯代斯普林杰克逊酒店,spring,rest,spring-boot,jackson,unmarshalling,Spring,Rest,Spring Boot,Jackson,Unmarshalling,正在尝试创建restful服务以保存“PeriodeSeignment”,如下所示: package DomainModel.Enseignement.Notations; import java.time.MonthDay; import javax.persistence.Basic; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedVa
package DomainModel.Enseignement.Notations;
import java.time.MonthDay;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
import org.springframework.format.annotation.DateTimeFormat;
import com.fasterxml.jackson.annotation.JsonFormat;
import DomainModel.Enseignement.UniteeEnseignement;
@Entity
@Table(name = "PERIODES_ENSEIGNEMENTS")
public class PeriodeEnseignement implements UniteeEnseignement {
private Integer id;
private String nom;
private MonthDay debut;
private MonthDay fin;
@Id
@Column(name = "ID")
@GeneratedValue(generator = "UseExistingOrGenerateIdGenerator")
@GenericGenerator(name = "UseExistingOrGenerateIdGenerator", strategy = "UsefulEntities.UseExistingOrGenerateIdGenerator")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Basic
@Column(name = "NOM")
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
@JsonFormat(pattern = "dd/MM")
@DateTimeFormat(pattern = "dd/MM")
public MonthDay getDebut() {
return debut;
}
public void setDebut(MonthDay debut) {
this.debut = debut;
}
@JsonFormat(pattern = "dd/MM")
@DateTimeFormat(pattern = "dd/MM")
public MonthDay getFin() {
return fin;
}
public void setFin(MonthDay fin) {
this.fin = fin;
}
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.modules(new JavaTimeModule());
return builder;
}
但是注释字段出现了问题,原因是:
@JsonFormat(pattern = "dd/MM")
@DateTimeFormat(pattern = "dd/MM")
我已经持久化了一些其他实体,它们的工作方式类似于一个符咒,但它们不包含MonthDay属性(它可以与包含LocalDate的实体一起工作)
这是我的restfulcontroller:
@RestController
public class PeriodeEnseignementServices implements GenericUniteeEnseignementService<PeriodeEnseignement> {
@RequestMapping(value = "/periodeEnseignementService/registerPeriodeEnseignementService", method = RequestMethod.POST)
private GenericResponse registerPeriodeEnseignement(PeriodeEnseignement periodeEnseignement) {
return this.insertNewUniteeEnseignement(periodeEnseignement, this.periodeEnseignementRepository);
}
}
那么,如何正确地整理/取消整理MonthDay属性呢
提前谢谢
{timestamp: 1552686924075, status: 400, error: "Bad Request", errors: [{,…}, {,…}],…}
error: "Bad Request"
errors: [{,…}, {,…}]
0: {,…}
arguments: [{codes: ["periodeEnseignement.debut", "debut"], arguments: null, defaultMessage: "debut",…}]
0: {codes: ["periodeEnseignement.debut", "debut"], arguments: null, defaultMessage: "debut",…}
arguments: null
code: "debut"
codes: ["periodeEnseignement.debut", "debut"]
0: "periodeEnseignement.debut"
1: "debut"
defaultMessage: "debut"
bindingFailure: true
code: "typeMismatch"
codes: ["typeMismatch.periodeEnseignement.debut", "typeMismatch.debut", "typeMismatch.java.time.MonthDay",…]
0: "typeMismatch.periodeEnseignement.debut"
1: "typeMismatch.debut"
2: "typeMismatch.java.time.MonthDay"
3: "typeMismatch"
defaultMessage: "Failed to convert property value of type 'java.lang.String' to required type 'java.time.MonthDay' for property 'debut'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@com.fasterxml.jackson.annotation.JsonFormat @org.springframework.format.annotation.DateTimeFormat java.time.MonthDay] for value '07/02'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [07/02]"
field: "debut"
objectName: "periodeEnseignement"
rejectedValue: "07/02"
1: {,…}
arguments: [{codes: ["periodeEnseignement.fin", "fin"], arguments: null, defaultMessage: "fin", code: "fin"}]
0: {codes: ["periodeEnseignement.fin", "fin"], arguments: null, defaultMessage: "fin", code: "fin"}
arguments: null
code: "fin"
codes: ["periodeEnseignement.fin", "fin"]
0: "periodeEnseignement.fin"
1: "fin"
defaultMessage: "fin"
bindingFailure: true
code: "typeMismatch"
codes: ["typeMismatch.periodeEnseignement.fin", "typeMismatch.fin", "typeMismatch.java.time.MonthDay",…]
0: "typeMismatch.periodeEnseignement.fin"
1: "typeMismatch.fin"
2: "typeMismatch.java.time.MonthDay"
3: "typeMismatch"
defaultMessage: "Failed to convert property value of type 'java.lang.String' to required type 'java.time.MonthDay' for property 'fin'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@com.fasterxml.jackson.annotation.JsonFormat @org.springframework.format.annotation.DateTimeFormat java.time.MonthDay] for value '01/12'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [01/12]"
field: "fin"
objectName: "periodeEnseignement"
rejectedValue: "01/12"
message: "Validation failed for object='periodeEnseignement'. Error count: 2"
path: "/periodeEnseignementService/registerPeriodeEnseignementService"
status: 400
timestamp: 1552686924075
[编辑#2]
从属性中删除@DateTimeFormat、添加@RequestBody并公开register方法后,客户端控制台中出现另一个错误:
POST http://localhost:8080/periodeEnseignementService/registerPeriodeEnseignementService 415
send @ jquery-3.3.1.js:9600
ajax @ jquery-3.3.1.js:9206
jQuery.(anonymous function) @ jquery-3.3.1.js:9355
(anonymous) @ utils_end_file.js:13
dispatch @ jquery-3.3.1.js:5183
elemData.handle @ jquery-3.3.1.js:4991
error: "Unsupported Media Type"
message: "Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported"
path: "/periodeEnseignementService/registerPeriodeEnseignementService"
status: 415
timestamp: 1552811644305
[编辑#3]
在客户端从post更改为ajax以发送json格式请求后,我遇到了另一个错误
error: "Bad Request"
message: "JSON parse error: Cannot construct instance of `DomainModel.Enseignement.Notations.PeriodeEnseignement` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('id=5&nom=sdsdfsfd&debut=13%2F03&fin=17%2F03'); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `DomainModel.Enseignement.Notations.PeriodeEnseignement` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('id=5&nom=sdsdfsfd&debut=13%2F03&fin=17%2F03')↵ at [Source: (PushbackInputStream); line: 1, column: 1]"
path: "/periodeEnseignementService/registerPeriodeEnseignementService"
status: 400
timestamp: 1552820002498
注意:PeriodeSeignment确实有一个默认构造函数。当您使用
Java8
Time
包和Jackson
在ObjectMapper
中注册JavaTimeModule
时:
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
在Spring
中,您可以按如下方式对其进行自定义:
package DomainModel.Enseignement.Notations;
import java.time.MonthDay;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
import org.springframework.format.annotation.DateTimeFormat;
import com.fasterxml.jackson.annotation.JsonFormat;
import DomainModel.Enseignement.UniteeEnseignement;
@Entity
@Table(name = "PERIODES_ENSEIGNEMENTS")
public class PeriodeEnseignement implements UniteeEnseignement {
private Integer id;
private String nom;
private MonthDay debut;
private MonthDay fin;
@Id
@Column(name = "ID")
@GeneratedValue(generator = "UseExistingOrGenerateIdGenerator")
@GenericGenerator(name = "UseExistingOrGenerateIdGenerator", strategy = "UsefulEntities.UseExistingOrGenerateIdGenerator")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Basic
@Column(name = "NOM")
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
@JsonFormat(pattern = "dd/MM")
@DateTimeFormat(pattern = "dd/MM")
public MonthDay getDebut() {
return debut;
}
public void setDebut(MonthDay debut) {
this.debut = debut;
}
@JsonFormat(pattern = "dd/MM")
@DateTimeFormat(pattern = "dd/MM")
public MonthDay getFin() {
return fin;
}
public void setFin(MonthDay fin) {
this.fin = fin;
}
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.modules(new JavaTimeModule());
return builder;
}
编辑将方法签名更新为:
public GenericResponse registerPeriodeEnseignement(@RequestBody PeriodeEnseignement periodeEnseignement)
使用
@RequestBody
注释并将方法公开
经过多次修改,我终于解决了这个问题
1-将客户端调用从jQuery.post更改为$.ajax调用,如下所示
var form = $('#myForm');
var jsonFormData = getFormData(form);
$.ajax({
url : "/path/to/web/service/controller",
type : "POST",
dataType : "json",
contentType : "application/json",
data : JSON.stringify(jsonFormData),
complete : function() {
},
success : function(data) {
alert("success !");
},
error : function() {
alert("failed !");
},
});
});
function getFormData($form) {
var unindexed_array = $form.serializeArray();
var indexed_array = {};
$.map(unindexed_array, function(n, i) {
indexed_array[n['name']] = n['value'];
});
return indexed_array;
}
2-将@RequestBody添加到我的服务端例程中:
@RequestMapping(value = "/periodeEnseignementService/registerPeriodeEnseignementService", method = RequestMethod.POST, produces = "application/json", consumes = "application/json")
public GenericResponse registerPeriodeEnseignement(@RequestBody PeriodeEnseignement periodeEnseignement) {
return this.insertNewUniteeEnseignement(periodeEnseignement, this.periodeEnseignementRepository);
}
3-POJO类中不需要@DateTimeFormatter和@JsonFormat(“dd/MMM”)
4-必须为java.time.MonthDay配置JsonSerializer和JsonDeserializer,否则,字段保留为空
@Bean
public ObjectMapper objectMapperBuilder() {
SimpleModule msJavaTimeModule = new SimpleModule();
msJavaTimeModule.addSerializer(MonthDay.class, new JsonSerializer<MonthDay>() {
@Override
public void serialize(MonthDay value, JsonGenerator gen, SerializerProvider serializers)
throws IOException {
gen.writeStartObject();
gen.writeStringField("label", value.format(DateTimeFormatter.ofPattern("dd MMM", Locale.FRANCE)));
gen.writeEndObject();
}
});
msJavaTimeModule.addDeserializer(MonthDay.class, new JsonDeserializer<MonthDay>() {
@Override
public MonthDay deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonNode node = p.getCodec().readTree(p);
String content = node.asText();
int slashIndex = content.indexOf('/');
String dayAsString = content.substring(0, slashIndex);
String monthAsString = content.substring(slashIndex + 1);
int day = Integer.parseInt(dayAsString);
int month = Integer.parseInt(monthAsString);
return MonthDay.of(month, day);
}
});
ObjectMapper objectMapper = new Jackson2ObjectMapperBuilder().modules(msJavaTimeModule).build();
return objectMapper;
}
@Bean
公共对象映射器objectMapperBuilder(){
SimpleModule msJavaTimeModule=新SimpleModule();
msJavaTimeModule.addSerializer(MonthDay.class,新的JsonSerializer()){
@凌驾
public void序列化(MonthDay值、JsonGenerator gen、SerializerProvider序列化器)
抛出IOException{
gen.writeStartObject();
gen.writeStringField(“label”,value.format(模式的DateTimeFormatter.of(“dd MMM”,Locale.FRANCE));
writeEndObject将军();
}
});
msJavaTimeModule.addDeserializer(MonthDay.class,新的JsonDeserializer()){
@凌驾
public MonthDay反序列化(JsonParser,反序列化上下文ctxt)
抛出IOException、JsonProcessingException{
JsonNode node=p.getCodec().readTree(p);
字符串内容=node.asText();
int slashIndex=content.indexOf('/');
String dayaString=content.substring(0,slashIndex);
字符串monthastring=content.substring(slashIndex+1);
int day=Integer.parseInt(dayaString);
int month=Integer.parseInt(monthastring);
返回月日(月日);
}
});
ObjectMapper ObjectMapper=new Jackson2ObjectMapperBuilder().modules(msJavaTimeModule.build();
返回对象映射器;
}
感谢米查·齐奥伯的指导 我添加了一个@configuration类,并将这部分代码放在那里,调用了该方法,但仍然存在相同的问题:/@SidiMohamedMOULEYSLIMANE,您能否展示您的示例
JSON
负载和异常堆栈跟踪?也许会有一些细节来帮助发现错误。您的类和控制器看起来正常。问题是没有引发异常,服务器在使用“PeriodenSeignment”作为参数时不执行RegisterPeriodeEnSignement(PeriodenSeignement PeriodenSeignement),并且在没有执行时进行响应,我确信解组过程正在失败,因此服务器不会回复:/。。。在使用JsonFormat和JsonFormat注释LocalDate之前,LocalDate(在另一个restfulcontroller中)也存在同样的问题DateTimeFormat@SidiMohamedMOULEYSLIMANE,什么是JSON
有效负载?若控制器未触发,则可能是请求错误。这是来自google chrome的,似乎无法按预期将字符串转换为MonthDay::/