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

Posted

技术标签:

【中文标题】将 json 对象中的元素数组保存到不同的行中【英文标题】:Saving arrays of elements in the json object into different rows 【发布时间】:2019-08-31 23:30:57 【问题描述】:

在保存包含多个 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);
    

道-保存

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】:

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

    JSON 解析为List<JsonPerson>List<JsonPerson> 转换为List<Person> 打印List<Person>(可以保存到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

上面的代码打印:

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

以上代码将解析JSON 与其他部分分开。另外,不要在每个POJO 中创建ObjectMapperPOJO 应该对 ObjectMapperJackson 一无所知。

更新

因为nameJSON Object,您可以使用firstlast 属性创建新的POJO - Name,或者将其与phone 类似地处理并反序列化为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

上面的代码修改后应该打印出来:

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

getNameAsString 方法被简化,您需要处理所有极端情况并为nullemptysemi-empty 节点创建更好的String 表示。

【讨论】:

谢谢 Michal,我已经更新了我的问题,因为我有多个 json 列,但只有 phone 列需要保存在不同的行中。此外,在读取值 List jsonPersons = mapper.readValue(jsonFile, personType); 我如何捕获传入的 json 请求值?我在模态类中使用了mapper.readtree,在保存到数据库之前对其进行了转换。 @404or505,如果其他属性是复杂对象,您始终可以将它们反序列化为POJO 类或*Node 类。更新后看看我的答案。

以上是关于将 json 对象中的元素数组保存到不同的行中的主要内容,如果未能解决你的问题,请参考以下文章

Python - 如何将 python36 命令行中的行保存到 .py 文件中?

Python - 如何将python36命令行中的行保存到.py文件中?

如何将存储在列中的 JSON 数组中的每个元素的行拆分为一行?

如何在不同的行中添加 alertView 中的按钮?

如何将数据创建和更新为保存在各个行中的数组

将 JSON 对象保存到 Node 中的文件中 [重复]