存储类的JSON,引用同一个类的对象

时间:2018-05-17 13:25:48

标签: java json design-patterns

我有类似的东西:

public class Person {
    public String name;
    public List<Person> family;
}
List<Person> people;

我想将存储为磁盘上的JSON字符串。我想要遵循一个好的设计模式。就像以正确的方式做事

我不想以

结束
[{"name":"John Doe", "family": [{"name": "Mary", "family": [{"name": "Mary's mother", "family": [{.........

也有人可能最终将玛丽让约翰·多伊作为家人,进行无休止的递归。

我最终想要的是这样的事情:

[{"name":"John Doe", "family": [(reference to Mary)]}, {"name": "Mary", "family": [(reference to Mary's Mother), (reference to John Doe)]}, ...]

我不想假设名称是唯一的。

添加&#34; ID&#34;对人有好的实施/模式?因为在我的课堂上,有身份证的人没有意义(他们没有/不需要)

我想到的想法(我认为这是一个很好的设计模式)是让另一个&#34;私人&#34;班级

private class PersonWithId extends Person {
    private int id;
}

并将PersonWithId存储在JSON中,因此在存储族列表时,我可以将ID存储为引用,因此没有递归。

我有哪些选择?

感谢。

2 个答案:

答案 0 :(得分:2)

我将答案的范围限​​制在向序列化实例添加唯一标识符和避免循环引用的直接问题。

Jackson library支持循环引用。您可以管理唯一标识符的生成并告诉jackson引用它,或者让Jackson在json中生成唯一标识符。该库将能够将这样的json加载回内存:

// annotation that tells jackson to generate sequantial int unique id
// and add it as "@id" property
// this will also be used in de-serialization
@JsonIdentityInfo(
    generator = ObjectIdGenerators.IntSequenceGenerator.class,
    property="@id")
public class Person {
    public String name;
    public List<Person> family = new ArrayList<>();
}

测试方法:

public static void main(String[] args) {
    Person john = new Person();
    john.name = "John Doe";
    Person mary = new Person();
    mary.name = "Mary";
    john.family.add(mary);
    mary.family.add(john);
    List<Person> people = new ArrayList<>();
    people.add(john);
    people.add(mary);

    ObjectMapper mapper = new ObjectMapper();
    try {
        // serialize the list into json
        String json = mapper.writeValueAsString(people);
        System.out.println(json);

        // de-serialize the json into list of persons
        people = mapper.readValue(json, new TypeReference<List<Person>>(){});
        people.forEach(p -> System.out.println(p.name));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

输出:

[{"@id":1,"name":"John Doe","family":[{"@id":2,"name":"Mary","family":[1]}]},2]
John Doe
Mary

答案 1 :(得分:-1)

你可以这样做。

public class Person {

private static Map<UUID, Person> persons = new HashMap<>();

//some dummy data
static {
    final UUID uuidMax = UUID.randomUUID();
    persons.put(uuidMax, new Person("Max", null));
    persons.put(UUID.randomUUID(), new Person("John", Arrays.asList(uuidMax)));
}

public static String saveAsJSON() {
    Gson gson = new Gson();
    return gson.toJson(persons); 
    //or write right away gson.toJson(obj, new FileWriter("D:\\file.json"));
}

public static void addFromJSON(String json) {
    Gson gson = new GsonBuilder().create();
    persons = gson.fromJson(json, Map.class); 
    //plug in JsonReader reader = new JsonReader(new FileReader(filename)) to read directly from file
}

private String name;
private List<UUID> family;

public Person(String name, List<UUID> family) {
    this.name = name;
    this.family = family;
}

//returns family member if it exists
public Person getFamilyMember(UUID id) {
    if(persons.containsKey(id))
        return persons.get(id);
    return null;
}

//returns the entire family
public List<Person> getFamilyMembers() {
    List<Person> family = new LinkedList<>();
    if(this.family != null) {
        for (var cur : this.family) {
            var person = getFamilyMember(cur);
            if(person != null)
                family.add(person);
            else
                this.family.remove(cur); //person no longer exists

        }
    }
    return family;
}

}

使用GSON Library

<dependencies>
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.4</version>
    </dependency>
</dependencies>

UUID很棒,因为您不必担心生成唯一ID,因为它们通常是唯一的,这就是重点。理论上你可以得到重复,但这是非常不可能的。

它吐出的字符串,如下所示

{"bced5dcf-102c-4d18-9f92-bb10d7a5b212":{"name":"Max"},"e40710b4-55b5-4e97-a280-6d07ae160e3b":{"name":"John","family":["bced5dcf-102c-4d18-9f92-bb10d7a5b212"]}}

你可能想把Save / Read的东西放到另一个类中,但我只是把它全部放在那里作为例子。