我应该如何将 JSON(在其键之一中包含数组结构)解析为带有杰克逊的对象?



我正在尝试将对象解析为 json 字符串并将该字符串解析回新对象。但是当我尝试再次将 json 字符串解析回对象时,我遇到了问题。

这是我正在使用的 json 字符串的示例:

{
"timestamp" : 1568937539011,
"hash" : "7f1460c82223320fa7a384aaa7945e1413b404bb4261f6f59af2accb212ff249",
"previousHash" : "0",
"merkleRoot" : "67bbcd20039b18e792604614337983bcf0ff0c63b6c65e77933e77a3d655dbaf",
"transactions" : [ {
"transactionID" : "67bbcd20039b18e792604614337983bcf0ff0c63b6c65e77933e77a3d655dbaf",
"owner" : "Genesis Block",
"fileName" : "Genesis Block",
"fileHash" : "89eb0ac031a63d2421cd05a2fbe41f3ea35f5c3712ca839cbf6b85c4ee07b7a3"
} ]
}

我很困惑为什么我会遇到这个问题,因为这个网站上还有其他例子几乎回避了这个问题。经过数小时的阅读和搜索网络,我无法找出解决方案。

我的对象几乎由块和交易组成:

public class Block{
private long timestamp;
private String hash;
private String previousHash;
private String merkleRoot;
private List<Transaction> transactions = new ArrayList<Transaction>();
... Getters and setters ...
}
public class Transaction {
private String transactionID; 
private String owner;
private String fileName;
private String fileHash;
... Getters and setters ...
}

这是我的主要:

Block block = new Block("");
Transaction tr = new Transaction("Genesis Block", "Genesis Block", applySha256("Genesis Block"));
List<Transaction> trP = new ArrayList<Transaction>();
trP.add(tr);
block.setTransactions(trP);
block.doSomeHashCalculation();
String json = null;
String json2 = null;
try {
ObjectMapper mapper = new ObjectMapper();
json = mapper.writeValueAsString(block);
json2 = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(block);
} catch (IOException e) {
System.out.println("objectToJson(Object) has failed!");
}
System.out.println(json+"nn"+json2);
Block block2 = new Block("");
try {
ObjectMapper mapper = new ObjectMapper();
block2 = mapper.readValue(json, Block.class);
} catch (IOException e) {
System.out.println("jsonToBlock(String) has failed!");
}
.....Parsing block2 back into json here....

这是我从运行代码中得到的:

{"timestamp":1568948813041,"hash":"cdbd5d362cbc4cacc5c22c6868d498ca3e92197bf527ce11ab2ad7a558cfd4c2","previousHash":"0","merkleRoot":"67bbcd20039b18e792604614337983bcf0ff0c63b6c65e77933e77a3d655dbaf","transactions":[{"transactionID":"67bbcd20039b18e792604614337983bcf0ff0c63b6c65e77933e77a3d655dbaf","owner":"Genesis Block","fileName":"Genesis Block","fileHash":"89eb0ac031a63d2421cd05a2fbe41f3ea35f5c3712ca839cbf6b85c4ee07b7a3"}]}
{
"timestamp" : 1568948813041,
"hash" : "cdbd5d362cbc4cacc5c22c6868d498ca3e92197bf527ce11ab2ad7a558cfd4c2",
"previousHash" : "0",
"merkleRoot" : "67bbcd20039b18e792604614337983bcf0ff0c63b6c65e77933e77a3d655dbaf",
"transactions" : [ {
"transactionID" : "67bbcd20039b18e792604614337983bcf0ff0c63b6c65e77933e77a3d655dbaf",
"owner" : "Genesis Block",
"fileName" : "Genesis Block",
"fileHash" : "89eb0ac031a63d2421cd05a2fbe41f3ea35f5c3712ca839cbf6b85c4ee07b7a3"
} ]
}
jsonToBlock(String) has failed!

我认为,List属性使整个问题复杂化。我什至尝试过这样的事情:

JsonNode node = new ObjectMapper().readTree(json);
ObjectMapper mapper = new ObjectMapper();
Block block = new Block();
block.setTimestamp(node.get("timestamp").longValue());
block.setHash(node.get("hash").textValue());
block.setPreviousHash(node.get("previousHash").textValue());
block.setMerkleRoot(node.get("merkleRoot").textValue());
// Sadly the code below doesn't work
String tJson = node.get("transactions").textValue();
List<Transaction> tr = mapper.readValue(tJson, new TypeReference<List<Transaction>>() {});
block.setTransactions(tr);

我将非常感谢您能给我的任何帮助

编辑: 这是我从打印堆栈跟踪中获得的

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `test.Block` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (String)"{"timestamp":1568950470443,"hash":"ce4a443a1c7d7f29e28dd6a3f72df58c143c1d025b52fa0d770e8e2cf3793604","previousHash":"0","merkleRoot":"67bbcd20039b18e792604614337983bcf0ff0c63b6c65e77933e77a3d655dbaf","transactions":[{"transactionID":"67bbcd20039b18e792604614337983bcf0ff0c63b6c65e77933e77a3d655dbaf","owner":"Genesis Block","fileName":"Genesis Block","fileHash":"89eb0ac031a63d2421cd05a2fbe41f3ea35f5c3712ca839cbf6b85c4ee07b7a3"}]}"; line: 1, column: 2]
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1343)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1032)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1297)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:326)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4014)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3005)
at test.Main.main(Main.java:66)

@JsonSerialize并根据需要覆盖您自己的序列化程序。或者使用 gson 包中的 JsonObject

Gson g = new Gson();
XXXXX p = g.fromJson(jsonString, XXXXX.class)

看起来有一个非默认构造函数一直是问题所在。感谢您的快速评论,我需要阅读更多关于杰克逊的信息,因为我对此很陌生。

看起来这里已经回答了这个问题。 在我为Block.javaTransaction.java添加默认构造函数后,它对我有用 问题中没有指定Block.javaTransaction.java的构造函数参数,所以我做了一些假设。

public class Block {
private long timestamp;
private String hash;
private String previousHash;
private String merkleRoot;
private List<Transaction> transactions = new ArrayList<Transaction>();
Block() {
}
Block(String merkleRoot) {
this.merkleRoot = merkleRoot;
}
... Getters and setters ...
}
public class Transaction {
private String transactionID;
private String owner;
private String fileName;
private String fileHash;
Transaction() {
}
Transaction(String owner, String fileName, String fileHash) {
this.owner = owner;
this.fileName = fileName;
this.fileHash = fileHash;
}
... Getters and setters ...
}
public class Main {
public static void main(String[] args) {
String jsonString = "{"timestamp":1568948813041,"hash":"cdbd5d362cbc4cacc5c22c6868d498ca3e92197bf527ce11ab2ad7a558cfd4c2","previousHash":"0","merkleRoot":"67bbcd20039b18e792604614337983bcf0ff0c63b6c65e77933e77a3d655dbaf","transactions":[{"transactionID":"67bbcd20039b18e792604614337983bcf0ff0c63b6c65e77933e77a3d655dbaf","owner":"Genesis Block","fileName":"Genesis Block","fileHash":"89eb0ac031a63d2421cd05a2fbe41f3ea35f5c3712ca839cbf6b85c4ee07b7a3"}]}";
parseJson(jsonString);
}
private static void parseJson(String jsonString) {
try {
ObjectMapper objectMapper = new ObjectMapper();
Block block = objectMapper.readValue(jsonString, Block.class);
System.out.println(block.toString());
System.out.println(block.getTransactions().get(0).getOwner());
} catch (JsonProcessingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

最新更新