Как мне проанализировать JSON (который содержит структуру массива в одном из его ключей) для объекта с Джексоном? - PullRequest
1 голос
/ 20 сентября 2019

Я пытаюсь разобрать объект в строку 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 ...
}

И это мойmain:

        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+"\n\n"+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)

Ответы [ 3 ]

0 голосов
/ 20 сентября 2019

Похоже, что иметь конструктор не по умолчанию было проблемой все время.Спасибо за быстрый комментарий, мне нужно больше читать о Джексоне, так как я довольно новичок в этом.

0 голосов
/ 20 сентября 2019

Похоже, что здесь уже был дан ответ.Он работал для меня после того, как я добавил конструктор по умолчанию для Block.java и Transaction.java Параметры конструктора для Block.java и Transaction.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();
        }
    }
}
0 голосов
/ 20 сентября 2019

@ JsonSerialize и переопределите свой собственный сериализатор, если хотите.Или используйте JsonObject из пакета gson

Gson g = new Gson();
XXXXX p = g.fromJson(jsonString, XXXXX.class)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...