简体   繁体   中英

Serialization/Deserialization JSON Jackson HashMap JAVA

I have a simple problem, but I cannot find a solution by myself.

I need serialize two maps. One has Object as key and Integer as value. Another One has similar properties but key-object contains a list.

Here are my models.

Detail

package Model;


/**
 * Created by kh0ma on 01.11.16.
 */
public class Detail {
    private String name;

    public Detail() {
    }

    public Detail(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Detail{" +
                "name='" + name + '\'' +
                '}';
    }
}

Mechanism

package Model;



import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by kh0ma on 01.11.16.
 */
public class Mechanism {
    private String name;
    private List<Detail> details;

    public Mechanism(String name) {
        this.name = name;
        this.details = new ArrayList<Detail>();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }


    public List<Detail> getDetails() {
        return details;
    }

    public void setDetails(List<Detail> details) {
        this.details = details;
    }

    @Override
    public String toString() {
        return "Mechanism{" +
                "name='" + name + '\'' +
                ", details=" + details +
                '}';
    }
}

Then I pull data in maps by another class.

PullData

package PullData;

import Model.Detail;
import Model.Mechanism;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by kh0ma on 01.11.16.
 */
public class PullData {
    public static Map<Detail,Integer> DETAILS = new HashMap<Detail, Integer>();

    public static Map<Mechanism,Integer> MECHANISMS = new HashMap<Mechanism, Integer>();


    private static Detail detail1 = new Detail("Wheel");
    private static Detail detail2 = new Detail("Frame");
    private static Detail detail3 = new Detail("Seat");
    private static Detail detail4 = new Detail("Engine");
    private static Detail detail5 = new Detail("Headlight");

    public static void pullDetails()
    {

        DETAILS.put(detail1,6);
        DETAILS.put(detail2,2);
        DETAILS.put(detail3,5);
        DETAILS.put(detail4,1);
        DETAILS.put(detail5,2);
    }

    public static void pullMechanisms()
    {
        Mechanism car = new Mechanism("Car");

        car.getDetails().add(detail1);
        car.getDetails().add(detail2);
        car.getDetails().add(detail3);
        car.getDetails().add(detail4);
        car.getDetails().add(detail5);

        Mechanism bicycle = new Mechanism("Bicycle");

        bicycle.getDetails().add(detail1);
        bicycle.getDetails().add(detail2);

        MECHANISMS.put(car,1);
        MECHANISMS.put(bicycle,1);
    }
}

Than I try to serialize and deserialize maps in main method.

TestJSON

package TestJSON;

import Model.Detail;
import Model.Mechanism;
import PullData.PullData;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.MapType;


import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by kh0ma on 01.11.16.
 */
public class TestJSON {
public static void main(String[] args) {
    PullData.pullDetails();
    PullData.pullMechanisms();

    System.out.println("=+=+=+=BEFORE JSON SERIALISATION=+=+=+=");

    System.out.println("-=-=-=-=-=Before changes=-=-=-=-=-=-");

    PullData.DETAILS.forEach((k, v) -> System.out.println(k));
    PullData.MECHANISMS.forEach((k, v) -> System.out.println(k));

    System.out.println("-=-=-=-=-=After changes=-=-=-=-=-=-");

    PullData.MECHANISMS.forEach((k, v) -> {
        if (k.getName().equals("Bicycle")) k.getDetails()
                .forEach((detail -> detail.setName(detail.getName() + "FirstChanges")));
    });

    PullData.DETAILS.forEach((k, v) -> System.out.println(k));
    PullData.MECHANISMS.forEach((k, v) -> System.out.println(k));

    System.out.println("=+=+=+=JSON Print=+=+=+=");

    ObjectMapper objectMapper = new ObjectMapper();

    File jsonFileDetails = new File("src/main/resources/json/jsonDetails.txt");
    File jsonFileMechanisms = new File("src/main/resources/json/jsonMechanisms.txt");

    try {
        objectMapper.writerWithDefaultPrettyPrinter().writeValue(jsonFileDetails, PullData.DETAILS);
        objectMapper.writerWithDefaultPrettyPrinter().writeValue(jsonFileMechanisms, PullData.MECHANISMS);
    } catch (JsonGenerationException e) {
        e.printStackTrace();
    } catch (JsonMappingException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    System.out.println("=+=+=+=AFTER JSON SERIALISATION=+=+=+=");

    System.out.println("-=-=-=-=-=Before changes=-=-=-=-=-=-");

    ObjectMapper mapper = new ObjectMapper();

    MapType mapType = mapper.getTypeFactory().constructMapType(HashMap.class, Mechanism.class, Integer.class);

    Map<Detail, Integer> detailesAfterJson = new HashMap<Detail, Integer>();
    Map<Mechanism, Integer> mechanismsAfterJson = new HashMap<Mechanism, Integer>();

    try {
        detailesAfterJson = mapper.readValue(jsonFileDetails, new TypeReference<HashMap<Detail, Integer>>() {});
        mechanismsAfterJson = mapper.readValue(jsonFileMechanisms, new TypeReference<Map<Mechanism, Integer>>() {});
    } catch (JsonGenerationException e) {
        e.printStackTrace();
    } catch (JsonMappingException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    detailesAfterJson.forEach((k, v) -> System.out.println(k));
    mechanismsAfterJson.forEach((k, v) -> System.out.println(k));
    }
}

First map serializes like this.

jsonDetails.txt

{
  "Detail{name='WheelFirstChanges'}" : 6,
  "Detail{name='FrameFirstChanges'}" : 2,
  "Detail{name='Seat'}" : 5,
  "Detail{name='Engine'}" : 1,
  "Detail{name='Headlight'}" : 2
}

And another one like this.

jsonMechanisms.txt

{
  "Mechanism{name='Car', details=[Detail{name='WheelFirstChanges'}, Detail{name='FrameFirstChanges'}, Detail{name='Seat'}, Detail{name='Engine'}, Detail{name='Headlight'}]}" : 1,
  "Mechanism{name='Bicycle', details=[Detail{name='WheelFirstChanges'}, Detail{name='FrameFirstChanges'}]}" : 1
}

In java console I have this output.

console_output

/usr/lib/jvm/jdk1.8.0_102/bin/java -Didea.launcher.port=7544 -Didea.launcher.bin.path=/home/kh0ma/idea-IU-162.1121.32/bin -Dfile.encoding=UTF-8 -classpath "/usr/lib/jvm/jdk1.8.0_102/jre/lib/charsets.jar:/usr/lib/jvm/jdk1.8.0_102/jre/lib/deploy.jar:/usr/lib/jvm/jdk1.8.0_102/jre/lib/ext/cldrdata.jar:/usr/lib/jvm/jdk1.8.0_102/jre/lib/ext/dnsns.jar:/usr/lib/jvm/jdk1.8.0_102/jre/lib/ext/jaccess.jar:/usr/lib/jvm/jdk1.8.0_102/jre/lib/ext/jfxrt.jar:/usr/lib/jvm/jdk1.8.0_102/jre/lib/ext/localedata.jar:/usr/lib/jvm/jdk1.8.0_102/jre/lib/ext/nashorn.jar:/usr/lib/jvm/jdk1.8.0_102/jre/lib/ext/sunec.jar:/usr/lib/jvm/jdk1.8.0_102/jre/lib/ext/sunjce_provider.jar:/usr/lib/jvm/jdk1.8.0_102/jre/lib/ext/sunpkcs11.jar:/usr/lib/jvm/jdk1.8.0_102/jre/lib/ext/zipfs.jar:/usr/lib/jvm/jdk1.8.0_102/jre/lib/javaws.jar:/usr/lib/jvm/jdk1.8.0_102/jre/lib/jce.jar:/usr/lib/jvm/jdk1.8.0_102/jre/lib/jfr.jar:/usr/lib/jvm/jdk1.8.0_102/jre/lib/jfxswt.jar:/usr/lib/jvm/jdk1.8.0_102/jre/lib/jsse.jar:/usr/lib/jvm/jdk1.8.0_102/jre/lib/management-agent.jar:/usr/lib/jvm/jdk1.8.0_102/jre/lib/plugin.jar:/usr/lib/jvm/jdk1.8.0_102/jre/lib/resources.jar:/usr/lib/jvm/jdk1.8.0_102/jre/lib/rt.jar:/home/kh0ma/Dropbox/JavaStuding/JavaRush/JavaRushHomeWork/Test JSON for ANTONIOPRIME/target/classes:/home/kh0ma/Dropbox/JavaStuding/JavaRush/JavaRushHomeWork/Test JSON for ANTONIOPRIME/lib/gson-2.7.jar:/home/kh0ma/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.2.3/jackson-databind-2.2.3.jar:/home/kh0ma/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.2.3/jackson-annotations-2.2.3.jar:/home/kh0ma/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.2.3/jackson-core-2.2.3.jar:/home/kh0ma/idea-IU-162.1121.32/lib/idea_rt.jar" com.intellij.rt.execution.application.AppMain TestJSON.TestJSON
=+=+=+=BEFORE JSON SERIALISATION=+=+=+=
-=-=-=-=-=Before changes=-=-=-=-=-=-
Detail{name='Wheel'}
Detail{name='Frame'}
Detail{name='Seat'}
Detail{name='Engine'}
Detail{name='Headlight'}
Mechanism{name='Car', details=[Detail{name='Wheel'}, Detail{name='Frame'}, Detail{name='Seat'}, Detail{name='Engine'}, Detail{name='Headlight'}]}
Mechanism{name='Bicycle', details=[Detail{name='Wheel'}, Detail{name='Frame'}]}
-=-=-=-=-=After changes=-=-=-=-=-=-
Detail{name='WheelFirstChanges'}
Detail{name='FrameFirstChanges'}
Detail{name='Seat'}
Detail{name='Engine'}
Detail{name='Headlight'}
Mechanism{name='Car', details=[Detail{name='WheelFirstChanges'}, Detail{name='FrameFirstChanges'}, Detail{name='Seat'}, Detail{name='Engine'}, Detail{name='Headlight'}]}
Mechanism{name='Bicycle', details=[Detail{name='WheelFirstChanges'}, Detail{name='FrameFirstChanges'}]}
=+=+=+=JSON Print=+=+=+=
=+=+=+=AFTER JSON SERIALISATION=+=+=+=
-=-=-=-=-=Before changes=-=-=-=-=-=-
Detail{name='Detail{name='Engine'}'}
Detail{name='Detail{name='Seat'}'}
Detail{name='Detail{name='Headlight'}'}
Detail{name='Detail{name='WheelFirstChanges'}'}
Detail{name='Detail{name='FrameFirstChanges'}'}
Mechanism{name='Mechanism{name='Bicycle', details=[Detail{name='WheelFirstChanges'}, Detail{name='FrameFirstChanges'}]}', details=[]}
Mechanism{name='Mechanism{name='Car', details=[Detail{name='WheelFirstChanges'}, Detail{name='FrameFirstChanges'}, Detail{name='Seat'}, Detail{name='Engine'}, Detail{name='Headlight'}]}', details=[]}

Process finished with exit code 0

As you can see the maps before and after have differences, but I need absolutely identical maps.

Can you suggest me the solution?

I downloaded clases into GitHub repository.

JSON_TEST

Thanks for your answers.

In JSON, keys must be strings. Your implementation uses the toString methods of Detail and Mechanism as keys. Since these methods return different strings, the JSON keys will be different.

I recommend to not use anything else than strings as map keys if you want to serialize to JSON.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM