我有类似的东西:
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存储为引用,因此没有递归。
我有哪些选择?
感谢。
答案 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的东西放到另一个类中,但我只是把它全部放在那里作为例子。