使用 spring 在 mongodb 中存储 JSON 模式

Storing a JSON schema in mongodb with spring

我是 Spring 数据和 mongodb 的新手。我有一个 JSON 对象,它表示 JSON 模式,我需要使用 spring 数据将其存储在 mongodb 中。但是 JSON 模式的问题是 JSON 模式的结构是动态的;例如,下面是两个具有完全不同结构的有效 JSON 模式。

{
    "type": "object",
    "properties": {
        "name": {
            "type": "string",
            "minLength": 10
        },
        "age": {
            "type": "integer"
        }
    },
    "required": [
        "name",
        "age"
    ]
}

{
    "type": "array",
    "items": {
        "type": "object",
        "properties": {
            "abc": {
                "type": "boolean"
            },
            "xyz": {
                "$ref": "#/definitions/"
            },
            "asd": {
                "type": "null"
            }
        },
        "required": [
            "abc",
            "xyz"
        ]
    }
}

如何定义一个 JAVA POJO Class 以便我可以将上面的 JSON 映射到定义的 class 并将其存储在 mongodb .或者是否可以在 spring 中执行 CURD 操作而不将其映射到 POJO class?

在我的项目中,我的模型结构非常动态,我使用 java.util.Map 对象

映射它们

我的 mondo 文档模型是这样实现的:

@Document(collection = "e_form_data")
public class FormDataModel extends AbstractModel
{
    private static final long serialVersionUID = -1733975205300782871L;
    @Field
    @Indexed(name = "e_form_id_idx")
    private String eFormId;
    @Field
    private Map<String, Object> eFormData;

    public FormDataModel()
    {
        super();
    }

    public FormDataModel(String id, String creatoDa, String modificatoDa, Date dataCreazione, Date dataModifica, String eFormId, Map<String, Object> eFormData)
    {
        super(id, creatoDa, modificatoDa, dataCreazione, dataModifica);
        this.eFormData = eFormData;
        this.eFormId = eFormId;
    }

    public FormDataModel(Map<String, Object> eFormData)
    {
        super();
        this.eFormData = eFormData;
    }

    public Map<String, Object> geteFormData()
    {
        return eFormData;
    }

    public void seteFormData(Map<String, Object> eFormData)
    {
        this.eFormData = eFormData;
    }

    public String geteFormId()
    {
        return eFormId;
    }

    public void seteFormId(String eFormId)
    {
        this.eFormId = eFormId;
    }

    public String getDataInserimento()
    {
        return Utils.formatDateTime(new DateTime(this.dataCreazione.getTime()), "dd/MM/yyyy");
    }

    @Override
    public String toString()
    {
        return "FormDataModel [eFormId=" + eFormId + ", eFormData=" + eFormData + "]";
    }

}

通过使用这个一切都很好

您可以使用 @DBref

映射嵌入式文档
@Document(collection = "first")
public class First {

    @Id
    private String id;

    @DBRef
    private Properties properties;

    @Field
    private List<String> required;

    // constructor
    // getters and setter    
}

public class Properties {

    @Id
    private String id;

    @DBRef
    private Name name;

    @DBRef
    private Age age;

    // constructor
    // getters and setter   
}

public class Name { ... }
public class Age { ... }

http://www.baeldung.com/cascading-with-dbref-and-lifecycle-events-in-spring-data-mongodb

http://docs.spring.io/spring-data/data-mongo/docs/1.4.2.RELEASE/reference/html/mapping-chapter.html#mapping-usage-references

或者按照 Angelo Immediata 的建议

@Document(collection = "first")
public class First {

    @Id
    private String id;

    @Field
    private Map<String, Object> properties;

    @Field
    private List<String> required;

    // constructor
    // getters and setter    
}

并且您将需要一些自定义读写转换器

http://docs.spring.io/spring-data/data-mongo/docs/1.4.2.RELEASE/reference/html/mapping-chapter.html#mapping-explicit-converters

请在此处找到必要的代码。

@lombok.Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class Bounty {

  String type;
  Map<String, Object> items;
  Map<String, Object> properties;
  List<Object> required;
}

这是我的存储库 class

public interface BountyRepository extends MongoRepository<Bounty, String> {
}

这是一个控制器片段,您可以用来试用

@GetMapping("/insert/{number}")
    public void insert(@PathVariable int number){
        bountyRepository.save(getBounty(number));
    }


    public Bounty getBounty(int number){
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonString1 = "{\n" +
            "    \"type\": \"object\",\n" +
            "    \"properties\": {\n" +
            "        \"name\": {\n" +
            "            \"type\": \"string\",\n" +
            "            \"minLength\": 10\n" +
            "        },\n" +
            "        \"age\": {\n" +
            "            \"type\": \"integer\"\n" +
            "        }\n" +
            "    },\n" +
            "    \"required\": [\n" +
            "        \"name\",\n" +
            "        \"age\"\n" +
            "    ]\n" +
            "}";


        String jsonString2 = "{\n" +
            "    \"type\": \"array\",\n" +
            "    \"items\": {\n" +
            "        \"type\": \"object\",\n" +
            "        \"properties\": {\n" +
            "            \"abc\": {\n" +
            "                \"type\": \"boolean\"\n" +
            "            },\n" +
            "            \"xyz\": {\n" +
            "                \"$ref\": \"#/definitions/\"\n" +
            "            },\n" +
            "            \"asd\": {\n" +
            "                \"type\": \"null\"\n" +
            "            }\n" +
            "        },\n" +
            "        \"required\": [\n" +
            "            \"abc\",\n" +
            "            \"xyz\"\n" +
            "        ]\n" +
            "    }\n" +
            "}";

        try {
            Bounty bounty1 = objectMapper.readValue(jsonString1, Bounty.class);
            Bounty bounty2 = objectMapper.readValue(jsonString2, Bounty.class);


            if (number == 1) return bounty1;
            if (number == 2) return bounty2;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

这是 Mongo 保存后的样子。

/* 1 */
{
    "_id" : ObjectId("58da2390fde4f133178499fa"),
    "_class" : "pani.kiran.sumne.model.Bounty",
    "type" : "object",
    "properties" : {
        "name" : {
            "type" : "string",
            "minLength" : 10
        },
        "age" : {
            "type" : "integer"
        }
    },
    "required" : [ 
        "name", 
        "age"
    ]
}

/* 2 */
{
    "_id" : ObjectId("58da23adfde4f133178499fb"),
    "_class" : "pani.kiran.sumne.model.Bounty",
    "type" : "array",
    "items" : {
        "type" : "object",
        "properties" : {
            "abc" : {
                "type" : "boolean"
            },
            "xyz" : {
                "$ref" : "#/definitions/"
            },
            "asd" : {
                "type" : "null"
            }
        },
        "required" : [ 
            "abc", 
            "xyz"
        ]
    }
}

我建议使用 MongoTemplate and serialize and deserailize using Gson/Jackson

Mongo 模板有 CRUD 方法,它采用集合名称和 DBObject 实体,这与直接使用 mongo java 驱动程序非常相似。

因此您将拥有 json 有效负载并使用映射器库之一将它们转换为 Map

类似

反序列化

ObjectMapper mapper = new ObjectMapper(); 
TypeReference<HashMap<String,Object>> typeRef 
        = new TypeReference<HashMap<String,Object>>() {};
HashMap<String,Object> map = mapper.readValue(jsonpayload, typeRef); 

DBObject

DBObject dbObject = new BasicDBObject(map);

Mongo模板

mongoTemplate.save(dbObject, "collectionname");

您可以对所有其他 CRUD 操作执行类似的操作。

FWIW,MongoDB 引入了 3.6 JSON Schema Validation support at the database level. You can read more on MongoDB's blog。希望能有所帮助!