如何使用骆驼在 java 中以固定长度数据格式编组 JSON 和重复组?
How to marshal JSON with repeating groups in a fixed length data format in java using camel?
我需要处理一个 JSON - 它有重复组
我需要把它转换成定长记录
{
"blockType" : "BL-H ",
"blockTypeLength" : "00000031",
"blockId" : "S62951156229900",
"totalNoOfTX" : "001",
"msgblockType" : "TX-S ",
"messageLength" : "00000728",
"noa":[
{
"title":"Behin",
"artist":"LIMP ",
"itunes_link":"http:behind"
},
{
"title":"Alone",
"artist":"ALYSS",
"itunes_link":"http:clk.doubler.com"
}
]
}
应转换为 BehinLIMP http:behindAloneALYSShttp:clk.doubler.com
我可以在请求中有一对多这样的组
我试过的-
DataFormat bindy = new BindyFixedLengthDataFormat(myModel.class);
from("direct:testUnmarshall")
.log("${body}")
//.unmarshal().json(JsonLibrary.Jackson, BillingBookingRequest[].class)
.inputType(BillingBookingRequest.class)
.process(new Processor() {
@Override
public void process(Exchange exchange) throws Exception {
try {
BillingBookingRequest responseBody = exchange.getMessage().getBody(BillingBookingRequest.class);
ZvkkRequest requestBody = new ZvkkRequest();
requestBody.setBlockType(responseBody.getBlockType());
requestBody.setBlockTypeLength(responseBody.getBlockTypeLength());
requestBody.setBlockId(responseBody.getBlockId());
requestBody.setTotalNoOfTX(responseBody.getTotalNoOfTX());
requestBody.setMsgblockType(responseBody.getMsgblockType());
requestBody.setMessageLength(responseBody.getMessageLength());
List<DAO> noaList = responseBody.getNoa();
List<DAOFix> repGrp = new ArrayList<>();
for (DAO noa:
noaList) {
DAOFix obj = new DAOFix();
obj.setArtist(noa.getArtist());obj.setTitle(noa.getTitle());obj.setItunes_link(noa.getItunes_link());
repGrp.add(obj);
}
requestBody.setRepeatingGrp(repGrp);
exchange.getOut().setBody(requestBody);
} catch (Exception exception){
System.out.println("EXCEPTION HERE :: "+exception.getMessage());
exception.printStackTrace();
}
}
})
.log("Before marshal ....... ${body}")
.marshal(bindy)
.log("After marshal ....... ${body}")
.to("{{file.path}}fileName=check.dat")
.end();
java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
also observed - org.apache.camel.NoTypeConversionAvailableException: No type converter available to convert from type: myFixedLengthRequestModel to the required type: java.io.InputStream with value myFixedLengthRequestModel[with all the values]
我使用了相应的模型来保存 json 的值以及@FixedLengthRecord
需要帮助来理解和解决这个问题。
public class ZvkkRequest {
@DataField(pos = 1, length=5, align = "L", paddingChar=' ')
private String blockType;
@DataField(pos = 2, length=8, align = "R", paddingChar='0')
private int blockTypeLength;
@DataField(pos = 3, length=15, align = "L", paddingChar=' ')
private String blockId;
@DataField(pos = 4, length=3, align = "R", paddingChar='0')
private int totalNoOfTX;
@DataField(pos = 5, length=5, align = "L", paddingChar=' ')
private String msgblockType;
@DataField(pos = 6, length=8, align = "R", paddingChar='0')
private int messageLength;
@OneToMany(mappedTo = "classpath.DAOFix")
private List<DAOFix> repeatingGrp;
}
class DAOFix {
@DataField(pos = 7, length=5, align = "R", paddingChar=' ')
private String title;
@DataField(pos = 8, length=5, align = "R", paddingChar=' ')
private String artist;
@DataField(pos = 9, length=5, align = "R", paddingChar=' ')
private String itunes_link;
}
对此进行了测试,似乎 @OneToMany
似乎无法像 BindyCsvDataFormat
那样与 BindyFixedLengthDataFormat
一起工作,这意味着您可能会处理 json并创建多个对象实例,然后您可以使用 Bindy 将其编组为固定长度的记录。
下面是我用来测试它的代码以及一种方法 (direct:bindyFixedLenghtProcessed
) 将单个 ZvkkRequest
实例转换为 ZvkkRequestFixedLenght
实例列表,然后您可以将其编组到BindyFixedLengthDataFormat
public class ExampleTests extends CamelTestSupport {
@Test
public void bindyCSVTest(){
// Test bindy @OneToMany with BindyCsvDataFormat
template.sendBody("direct:bindyCSV", testJson);
}
@Test
public void bindyFixedLenghtTest(){
// Test bindy @OneToMany with BindyFixedLengthDataFormat
template.sendBody("direct:bindyFixedLenght", testJson);
}
@Test
public void bindyFixedLenghtProcessedTest(){
// Test workaraound
template.sendBody("direct:bindyFixedLenghtProcessed", testJson);
}
@Override
protected RoutesBuilder createRouteBuilder() throws Exception {
return new RouteBuilder(){
@Override
public void configure() throws Exception {
// Doesn't seem to work with OneToMany
DataFormat bindyCSV = new BindyCsvDataFormat(ZvkkRequest.class);
from("direct:bindyCSV")
.unmarshal().json(JsonLibrary.Jackson, ZvkkRequest.class)
.marshal(bindyCSV)
.log("${body}");
DataFormat bindyFixedLenght = new BindyFixedLengthDataFormat(ZvkkRequest.class);
from("direct:bindyFixedLenght")
.unmarshal().json(JsonLibrary.Jackson, ZvkkRequest.class)
.marshal(bindyFixedLenght)
.log("${body}");
DataFormat bindyFixedLenght2 = new BindyFixedLengthDataFormat(ZvkkRequestFixedLenght.class);
from("direct:bindyFixedLenghtProcessed")
.unmarshal().json(JsonLibrary.Jackson, ZvkkRequest.class)
.process(new Processor(){
@Override
public void process(Exchange exchange) throws Exception {
ZvkkRequest body = exchange.getMessage()
.getBody(ZvkkRequest.class);
List<ZvkkRequestFixedLenght> requests = new ArrayList<>();
for (DAOFix it : body.noa) {
ZvkkRequestFixedLenght request = new ZvkkRequestFixedLenght();
request.blockType = body.blockType;
request.blockTypeLength = body.blockTypeLength;
request.blockId = body.blockId;
request.totalNoOfTX = body.totalNoOfTX;
request.msgblockType = body.msgblockType;
request.messageLength = body.messageLength;
request.artist = it.artist;
request.title = it.title;
request.itunesLink = it.itunesLink;
requests.add(request);
}
exchange.getMessage().setBody(requests);
}
})
.marshal(bindyFixedLenght2)
.log("${body}");
}
};
}
String testJson = "{" +
" \"blockType\" : \"BL-H \"," +
" \"blockTypeLength\" : \"00000031\"," +
" \"blockId\" : \"S62951156229900\"," +
" \"totalNoOfTX\" : \"001\"," +
" \"msgblockType\" : \"TX-S \"," +
" \"messageLength\" : \"00000728\"," +
" \"noa\":[" +
" {" +
" \"title\":\"Behin\"," +
" \"artist\":\"LIMP \"," +
" \"itunes_link\":\"http:behind\"" +
" }," +
" {" +
" \"title\":\"Alone\"," +
" \"artist\":\"ALYSS\"," +
" \"itunes_link\":\"http:clk.doubler.com\"" +
" }" +
" ]" +
"}";
}
bindyFixedLenghtProcessedTest 记录如下:
BL-H 00000031S62951156229900001TX-S 00000728BehinLIMP http:behind
BL-H 00000031S62951156229900001TX-S 00000728AloneALYSS http:clk.doubler.com
如果你想把它们放在 单行 上,你可以尝试分别编组 ZvkkRequest
和 DAOFix
并使用 字符串连接 将未编组的 DAOFix
条目组合成未编组的 ZvkkRequest
.
ZvkkRequest.java
@FixedLengthRecord
@CsvRecord(separator=",")
public class ZvkkRequest {
@DataField(pos = 1, length = 5, align = "L", paddingChar = ' ')
public String blockType;
@DataField(pos = 2, length = 8, align = "R", paddingChar = '0')
public int blockTypeLength;
@DataField(pos = 3, length = 15, align = "L", paddingChar = ' ')
public String blockId;
@DataField(pos = 4, length = 3, align = "R", paddingChar = '0')
public int totalNoOfTX;
@DataField(pos = 5, length = 5, align = "L", paddingChar = ' ')
public String msgblockType;
@DataField(pos = 6, length = 8, align = "R", paddingChar = '0')
public int messageLength;
@OneToMany
public List<DAOFix> noa;
}
DAOFix.java
public class DAOFix {
@DataField(pos = 7, length=5, align = "R", paddingChar=' ')
public String title;
@DataField(pos = 8, length=5, align = "R", paddingChar=' ')
public String artist;
@JsonProperty("itunes_link")
@DataField(pos = 9, length=30, align = "R", paddingChar=' ')
public String itunesLink;
}
ZvkkRequestFixedLenght.java
@CsvRecord(separator=",")
@FixedLengthRecord
public class ZvkkRequestFixedLenght {
@DataField(pos = 1, length = 5, align = "L", paddingChar = ' ')
public String blockType;
@DataField(pos = 2, length = 8, align = "R", paddingChar = '0')
public int blockTypeLength;
@DataField(pos = 3, length = 15, align = "L", paddingChar = ' ')
public String blockId;
@DataField(pos = 4, length = 3, align = "R", paddingChar = '0')
public int totalNoOfTX;
@DataField(pos = 5, length = 5, align = "L", paddingChar = ' ')
public String msgblockType;
@DataField(pos = 6, length = 8, align = "R", paddingChar = '0')
public int messageLength;
@DataField(pos = 7, length=5, align = "R", paddingChar=' ')
public String title;
@DataField(pos = 8, length=5, align = "R", paddingChar=' ')
public String artist;
@DataField(pos = 9, length=30, align = "R", paddingChar=' ')
public String itunesLink;
}
我需要处理一个 JSON - 它有重复组 我需要把它转换成定长记录
{
"blockType" : "BL-H ",
"blockTypeLength" : "00000031",
"blockId" : "S62951156229900",
"totalNoOfTX" : "001",
"msgblockType" : "TX-S ",
"messageLength" : "00000728",
"noa":[
{
"title":"Behin",
"artist":"LIMP ",
"itunes_link":"http:behind"
},
{
"title":"Alone",
"artist":"ALYSS",
"itunes_link":"http:clk.doubler.com"
}
]
}
应转换为 BehinLIMP http:behindAloneALYSShttp:clk.doubler.com
我可以在请求中有一对多这样的组
我试过的-
DataFormat bindy = new BindyFixedLengthDataFormat(myModel.class);
from("direct:testUnmarshall")
.log("${body}")
//.unmarshal().json(JsonLibrary.Jackson, BillingBookingRequest[].class)
.inputType(BillingBookingRequest.class)
.process(new Processor() {
@Override
public void process(Exchange exchange) throws Exception {
try {
BillingBookingRequest responseBody = exchange.getMessage().getBody(BillingBookingRequest.class);
ZvkkRequest requestBody = new ZvkkRequest();
requestBody.setBlockType(responseBody.getBlockType());
requestBody.setBlockTypeLength(responseBody.getBlockTypeLength());
requestBody.setBlockId(responseBody.getBlockId());
requestBody.setTotalNoOfTX(responseBody.getTotalNoOfTX());
requestBody.setMsgblockType(responseBody.getMsgblockType());
requestBody.setMessageLength(responseBody.getMessageLength());
List<DAO> noaList = responseBody.getNoa();
List<DAOFix> repGrp = new ArrayList<>();
for (DAO noa:
noaList) {
DAOFix obj = new DAOFix();
obj.setArtist(noa.getArtist());obj.setTitle(noa.getTitle());obj.setItunes_link(noa.getItunes_link());
repGrp.add(obj);
}
requestBody.setRepeatingGrp(repGrp);
exchange.getOut().setBody(requestBody);
} catch (Exception exception){
System.out.println("EXCEPTION HERE :: "+exception.getMessage());
exception.printStackTrace();
}
}
})
.log("Before marshal ....... ${body}")
.marshal(bindy)
.log("After marshal ....... ${body}")
.to("{{file.path}}fileName=check.dat")
.end();
java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
also observed - org.apache.camel.NoTypeConversionAvailableException: No type converter available to convert from type: myFixedLengthRequestModel to the required type: java.io.InputStream with value myFixedLengthRequestModel[with all the values]
我使用了相应的模型来保存 json 的值以及@FixedLengthRecord 需要帮助来理解和解决这个问题。
public class ZvkkRequest {
@DataField(pos = 1, length=5, align = "L", paddingChar=' ')
private String blockType;
@DataField(pos = 2, length=8, align = "R", paddingChar='0')
private int blockTypeLength;
@DataField(pos = 3, length=15, align = "L", paddingChar=' ')
private String blockId;
@DataField(pos = 4, length=3, align = "R", paddingChar='0')
private int totalNoOfTX;
@DataField(pos = 5, length=5, align = "L", paddingChar=' ')
private String msgblockType;
@DataField(pos = 6, length=8, align = "R", paddingChar='0')
private int messageLength;
@OneToMany(mappedTo = "classpath.DAOFix")
private List<DAOFix> repeatingGrp;
}
class DAOFix {
@DataField(pos = 7, length=5, align = "R", paddingChar=' ')
private String title;
@DataField(pos = 8, length=5, align = "R", paddingChar=' ')
private String artist;
@DataField(pos = 9, length=5, align = "R", paddingChar=' ')
private String itunes_link;
}
对此进行了测试,似乎 @OneToMany
似乎无法像 BindyCsvDataFormat
那样与 BindyFixedLengthDataFormat
一起工作,这意味着您可能会处理 json并创建多个对象实例,然后您可以使用 Bindy 将其编组为固定长度的记录。
下面是我用来测试它的代码以及一种方法 (direct:bindyFixedLenghtProcessed
) 将单个 ZvkkRequest
实例转换为 ZvkkRequestFixedLenght
实例列表,然后您可以将其编组到BindyFixedLengthDataFormat
public class ExampleTests extends CamelTestSupport {
@Test
public void bindyCSVTest(){
// Test bindy @OneToMany with BindyCsvDataFormat
template.sendBody("direct:bindyCSV", testJson);
}
@Test
public void bindyFixedLenghtTest(){
// Test bindy @OneToMany with BindyFixedLengthDataFormat
template.sendBody("direct:bindyFixedLenght", testJson);
}
@Test
public void bindyFixedLenghtProcessedTest(){
// Test workaraound
template.sendBody("direct:bindyFixedLenghtProcessed", testJson);
}
@Override
protected RoutesBuilder createRouteBuilder() throws Exception {
return new RouteBuilder(){
@Override
public void configure() throws Exception {
// Doesn't seem to work with OneToMany
DataFormat bindyCSV = new BindyCsvDataFormat(ZvkkRequest.class);
from("direct:bindyCSV")
.unmarshal().json(JsonLibrary.Jackson, ZvkkRequest.class)
.marshal(bindyCSV)
.log("${body}");
DataFormat bindyFixedLenght = new BindyFixedLengthDataFormat(ZvkkRequest.class);
from("direct:bindyFixedLenght")
.unmarshal().json(JsonLibrary.Jackson, ZvkkRequest.class)
.marshal(bindyFixedLenght)
.log("${body}");
DataFormat bindyFixedLenght2 = new BindyFixedLengthDataFormat(ZvkkRequestFixedLenght.class);
from("direct:bindyFixedLenghtProcessed")
.unmarshal().json(JsonLibrary.Jackson, ZvkkRequest.class)
.process(new Processor(){
@Override
public void process(Exchange exchange) throws Exception {
ZvkkRequest body = exchange.getMessage()
.getBody(ZvkkRequest.class);
List<ZvkkRequestFixedLenght> requests = new ArrayList<>();
for (DAOFix it : body.noa) {
ZvkkRequestFixedLenght request = new ZvkkRequestFixedLenght();
request.blockType = body.blockType;
request.blockTypeLength = body.blockTypeLength;
request.blockId = body.blockId;
request.totalNoOfTX = body.totalNoOfTX;
request.msgblockType = body.msgblockType;
request.messageLength = body.messageLength;
request.artist = it.artist;
request.title = it.title;
request.itunesLink = it.itunesLink;
requests.add(request);
}
exchange.getMessage().setBody(requests);
}
})
.marshal(bindyFixedLenght2)
.log("${body}");
}
};
}
String testJson = "{" +
" \"blockType\" : \"BL-H \"," +
" \"blockTypeLength\" : \"00000031\"," +
" \"blockId\" : \"S62951156229900\"," +
" \"totalNoOfTX\" : \"001\"," +
" \"msgblockType\" : \"TX-S \"," +
" \"messageLength\" : \"00000728\"," +
" \"noa\":[" +
" {" +
" \"title\":\"Behin\"," +
" \"artist\":\"LIMP \"," +
" \"itunes_link\":\"http:behind\"" +
" }," +
" {" +
" \"title\":\"Alone\"," +
" \"artist\":\"ALYSS\"," +
" \"itunes_link\":\"http:clk.doubler.com\"" +
" }" +
" ]" +
"}";
}
bindyFixedLenghtProcessedTest 记录如下:
BL-H 00000031S62951156229900001TX-S 00000728BehinLIMP http:behind
BL-H 00000031S62951156229900001TX-S 00000728AloneALYSS http:clk.doubler.com
如果你想把它们放在 单行 上,你可以尝试分别编组 ZvkkRequest
和 DAOFix
并使用 字符串连接 将未编组的 DAOFix
条目组合成未编组的 ZvkkRequest
.
ZvkkRequest.java
@FixedLengthRecord
@CsvRecord(separator=",")
public class ZvkkRequest {
@DataField(pos = 1, length = 5, align = "L", paddingChar = ' ')
public String blockType;
@DataField(pos = 2, length = 8, align = "R", paddingChar = '0')
public int blockTypeLength;
@DataField(pos = 3, length = 15, align = "L", paddingChar = ' ')
public String blockId;
@DataField(pos = 4, length = 3, align = "R", paddingChar = '0')
public int totalNoOfTX;
@DataField(pos = 5, length = 5, align = "L", paddingChar = ' ')
public String msgblockType;
@DataField(pos = 6, length = 8, align = "R", paddingChar = '0')
public int messageLength;
@OneToMany
public List<DAOFix> noa;
}
DAOFix.java
public class DAOFix {
@DataField(pos = 7, length=5, align = "R", paddingChar=' ')
public String title;
@DataField(pos = 8, length=5, align = "R", paddingChar=' ')
public String artist;
@JsonProperty("itunes_link")
@DataField(pos = 9, length=30, align = "R", paddingChar=' ')
public String itunesLink;
}
ZvkkRequestFixedLenght.java
@CsvRecord(separator=",")
@FixedLengthRecord
public class ZvkkRequestFixedLenght {
@DataField(pos = 1, length = 5, align = "L", paddingChar = ' ')
public String blockType;
@DataField(pos = 2, length = 8, align = "R", paddingChar = '0')
public int blockTypeLength;
@DataField(pos = 3, length = 15, align = "L", paddingChar = ' ')
public String blockId;
@DataField(pos = 4, length = 3, align = "R", paddingChar = '0')
public int totalNoOfTX;
@DataField(pos = 5, length = 5, align = "L", paddingChar = ' ')
public String msgblockType;
@DataField(pos = 6, length = 8, align = "R", paddingChar = '0')
public int messageLength;
@DataField(pos = 7, length=5, align = "R", paddingChar=' ')
public String title;
@DataField(pos = 8, length=5, align = "R", paddingChar=' ')
public String artist;
@DataField(pos = 9, length=30, align = "R", paddingChar=' ')
public String itunesLink;
}