将json对象中的元素数组保存到不同的行中

时间:2019-04-10 13:22:35

标签: json spring-boot spring-data-jpa spring-data spring-data-rest

在保存包含多个json的json对象时,该json对象被保存为单个数组而不是多个行。

样本json:

[
    {
     "id"   : 1, -- this is not a primary key and not unique but cannot be null
     "name" : "John Doe",
     "phone" : [
       { "type" : "home", "ref" : "111-111-1234"},
       { "type" : "work", "ref" : "222-222-2222"}
     ]
   },
   {
    "id"   : 2, -- this is not a primary key and not unique but cannot be null
    "name" : "Jane Doe",
    "phone" : [
      { "type" : "home", "ref" : "111-111-1234"},
      { "type" : "work", "ref" : "222-222-2222"}
    ]
  }
]

这是我保存到数据库后需要的

id   name         phone    
1    John Doe     { "type" : "home", "ref" : "111-111-1234"}
1    John Doe     { "type" : "work", "ref" : "222-222-2222"}
2    Jane Doe     { "type" : "home", "ref" : "111-111-1234"}
2    Jane Doe     { "type" : "work", "ref" : "222-222-2222"}

这就是我要得到的

id   name         phone    
1    John Doe     [{ "type" : "home", "ref" : "111-111-1234"},{ "type" : "work", "ref" : "222-222-2222"}]
2    Jane Doe    [{ "type" : "home", "ref" : "111-111-1234"},{ "type" : "work", "ref" : "222-222-2222"}]

这是我将json对象解析为pojo并保存到db

的方式
@Entity
@Table(name="person")
public class person{
    private Integer id;
    private String name;
    private String phone;
    @Transient 
    JsonNode phoneJson;

    private static OhjectMapper mapper = new ObjectMapper();

    getter/setter

    @Transient
    public JsonNode getPhoneJson(){
        return phoneJson;
    }

    public void setPhoneJson(JsonNode phoneJson){
        this.phoneJson = phoneJson;
    }

    @JsonIgnore
    @Column(name="phone")
    public String getPhone() throws Exception{
        return mapper.writeValueAsString(phoneJson);
    }

    public void setPhone(String phone) throws Exception{
        this.phone = mapper.readTree(phone);
    }
}

dao-保存

personRepository.save(person)

任何帮助将不胜感激。

更新

多个jSON列

[
    {
     "id"   : 1, -- this primary key and not unique but cannot be null
     "name" : { --this element can be empty/null
        "first" : "John",
        "last" : "Doe" 
      },
     "phone" : [
       { "type" : "home", "ref" : 1111111234},
       { "type" : "work", "ref" : 2222222222}
     ]
   },
   {
    "id"   : 2, -- this primary key and not unique but cannot be null
    "name" : {
        "first" : "Jane",
        "last" : "Doe" 
      },
    "phone" : [
      { "type" : "home", "ref" : 1111111234},
      { "type" : "work", "ref" : 2222222222}
    ]
  }
]

我如何获得如下结果

id   name                   phone    
1    [{John},{Doe}]     { "type" : "home", "ref" : "111-111-1234"}
1    [{John},{Doe}]     { "type" : "work", "ref" : "222-222-2222"}
2    [{Jane},{Doe}]     { "type" : "home", "ref" : "111-111-1234"}
2    [{Jane},{Doe}]     { "type" : "work", "ref" : "222-222-2222"}

1 个答案:

答案 0 :(得分:2)

您需要Person复制n个对象n次,其中phoneJSON数组的大小。为了明确起见,我建议创建两个单独的模型,我们可以分别使用这些模型来解析DB并将其保存在JSON中。您可以在下面找到一个简单的示例,

  1. List<JsonPerson>解析为List<JsonPerson>
  2. List<Person>转换为List<Person>
  3. 打印DB(您可以将其保存到import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.type.CollectionType; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class JsonApp { public static void main(String[] args) throws Exception { File jsonFile = new File("./resource/test.json").getAbsoluteFile(); ObjectMapper mapper = new ObjectMapper(); CollectionType personsType = mapper.getTypeFactory().constructCollectionType(List.class, JsonPerson.class); // parse List<JsonPerson> jsonPersons = mapper.readValue(jsonFile, personsType); // convert List<Person> persons = jsonPersons.stream() .map(p -> p.mapTo(mapper)) .flatMap(List::stream) .collect(Collectors.toList()); persons.forEach(System.out::println); // save persons to DB // ... } } class JsonPerson { private Integer id; private String name; private ArrayNode phone; public List<Person> mapTo(ObjectMapper mapper) { List<Person> persons = new ArrayList<>(); phone.elements().forEachRemaining(phone -> { persons.add(map(mapper, phone)); }); return persons; } private Person map(ObjectMapper mapper, JsonNode p) { Person person = new Person(); person.setId(id); person.setName(name); try { person.setPhone(mapper.writeValueAsString(p)); } catch (JsonProcessingException e) { throw new IllegalStateException(e); } return person; } // getters, setters, toString } class Person { private Integer id; private String name; private String phone; // getters, setters, toString }

示例:

Person{id=1, name='John Doe', phone='{"type":"home","ref":"111-111-1234"}'}
Person{id=1, name='John Doe', phone='{"type":"work","ref":"222-222-2222"}'}
Person{id=2, name='Jane Doe', phone='{"type":"home","ref":"111-111-1234"}'}
Person{id=2, name='Jane Doe', phone='{"type":"work","ref":"222-222-2222"}'}

上面的代码显示:

JSON

以上代码将解析ObjectMapper与其他部分分开。另外,请勿在每个POJO中创建POJOObjectMapperJacksonname一无所知。

更新

由于JSON ObjectPOJO,因此您可以使用Namefirst属性创建新的last-phone或将其与{{ 1}}并反序列化为JsonNode

class JsonPerson {

    private Integer id;
    private JsonNode name;
    private ArrayNode phone;

    public List<Person> mapTo(ObjectMapper mapper) {
        List<Person> persons = new ArrayList<>();
        phone.elements().forEachRemaining(phone -> {
            persons.add(map(mapper, phone));
        });

        return persons;
    }

    private Person map(ObjectMapper mapper, JsonNode p) {
        Person person = new Person();
        person.setId(id);
        person.setName(getNameAsString());
        try {
            person.setPhone(mapper.writeValueAsString(p));
        } catch (JsonProcessingException e) {
            throw new IllegalStateException(e);
        }

        return person;
    }

    private String getNameAsString() {
        if (name == null) {
            return null;
        }
        StringBuilder builder = new StringBuilder();
        if (name.isObject()) {
            ObjectNode nameObject = (ObjectNode) name;
            builder.append("[");
            builder.append("{").append(nameObject.get("first")).append("}");
            builder.append(",");
            builder.append("{").append(nameObject.get("last")).append("}");
            builder.append("]");
        }
        return builder.toString();
    }

    // getters, setters, toString
}

更改以上代码后,应打印:

Person{id=1, name='[{"John"},{"Doe"}]', phone='{"type":"home","ref":1111111234}'}
Person{id=1, name='[{"John"},{"Doe"}]', phone='{"type":"work","ref":2222222222}'}
Person{id=2, name='[{"Jane"},{"Doe"}]', phone='{"type":"home","ref":1111111234}'}
Person{id=2, name='[{"Jane"},{"Doe"}]', phone='{"type":"work","ref":2222222222}'}

getNameAsString方法已简化,您需要处理所有极端情况并为Stringnullempty节点创建更好的semi-empty表示形式。