简体   繁体   中英

While reading json data from my document DB, I want to add some configuration using which part of json structure would be transformed into a pojo

I have to come up with a design, basically a configuration that I can pass to a Mongo Reader job, to convert the read document(json) to a flat json structure. for eg(excuse the made up eg). Idea is that the json can be of any structure, but i should be able to control the output of the reader based on my mapping that i provide to this job.

animal: { dog: { name: pluto, age: 4 }, cat: { name: mini, age: 1 }, hamster: { name: jack age: 0.3 } }

TO

animals: [{ type: dog, name: pluto, age: 4 }, { type: cat, name: mini, age: 1 }, { type: hamster, name: jack, age: 1 } ]

Prepare utilities

Converters.java

import org.bson.Document;
import org.bson.json.Converter;
import org.bson.json.JsonMode;
import org.bson.json.JsonWriterSettings;
import org.bson.json.StrictJsonWriter;
import org.bson.types.ObjectId;

import java.util.List;
import java.util.stream.Collectors;

public class Converters {

    private Converters () {
    }

    private static class ObjectIdConverter implements Converter<ObjectId> {

        public static final Converters.ObjectIdConverter INSTANCE = new Converters.ObjectIdConverter();

        @Override
        public void convert(ObjectId value, StrictJsonWriter writer) {
            writer.writeString(value.toHexString());
        }
    }

    private static final JsonWriterSettings JSON_WRITER_SETTINGS = JsonWriterSettings
        .builder()
        .outputMode(JsonMode.RELAXED)
        .objectIdConverter(Converters.ObjectIdConverter.INSTANCE)
        .build();

    public static String bsonToJson(Document bson) {
        return bson == null ? null : bson.toJson(JSON_WRITER_SETTINGS);
    }

    public static String bsonListToJson(List<Document> bsonList) {
        return bsonList == null || bsonList.isEmpty() ? null :
            "[" + bsonList.stream()
                .map(Converters::bsonToJson)
                .collect(Collectors.joining(",")) +
            "]";
    }
}

JsonDao.java

import org.bson.BsonDocument;
import org.bson.BsonValue;
import org.bson.Document;
import org.bson.codecs.BsonArrayCodec;
import org.bson.codecs.DecoderContext;
import org.bson.json.JsonReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.BasicQuery;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class JsonDao {
    
    @Autowired
    private MongoTemplate mongoTemplate;

    public List<Document> findDocuments(String collectionName, String query, String projection) {
        return mongoTemplate.find(
            new BasicQuery(query, projection),
            Document.class,
            collectionName
        );
    }

    public List<Document> aggregateDocuments(String collectionName, String operations) {
        List<BsonDocument> pipeline = new BsonArrayCodec()
            .decode(new JsonReader(operations), DecoderContext.builder().build())
            .stream()
            .map(BsonValue::asDocument)
            .collect(Collectors.toList());
        return mongoTemplate.getDb().getCollection(collectionName).aggregate(pipeline).into(new ArrayList<>());
    }

    public String findJsonString(String collectionName, String query, String projection) {
        return bsonToJson(mongoTemplate.findOne(
            new BasicQuery(query, projection),
            Document.class,
            collectionName
        ));
    }

    public String findJsonArrayString(String collectionName, String query, String projection) {
        return bsonListToJson(findDocuments(collectionName, query, projection));
    }

    public String aggregateJsonString(String collectionName, String operations) {
        List<Document> documents = aggregateDocuments(collectionName, operations);
        return documents.isEmpty() ? null : bsonToJson(documents.get(0));
    }

    public String aggregateJsonArrayString(String collectionName, String operations) {
        return bsonListToJson(aggregateDocuments(collectionName, operations));
    }
}

Usage

implementation 'com.octomix.josson:josson:1.3.21'

-------------------------------------------------

String json = jsonDao.findJsonString(<collectionName>, <findOneQuery>, <projection>);
Josson josson = Josson.fromJsonString(json);
JsonNode node = josson.getNode(<transformationQuery>);
// Then use Jackson ObjectMapper to convert JsonNode to POJO

Test transformation

Josson josson = Josson.fromJsonString(
        "{\n" +
        "    \"animal\": {\n" +
        "        \"dog\": {\n" +
        "            \"name\": \"pluto\",\n" +
        "            \"age\": 4\n" +
        "        },\n" +
        "        \"cat\": {\n" +
        "            \"name\": \"mini\",\n" +
        "            \"age\": 1\n" +
        "        },\n" +
        "        \"hamster\": {\n" +
        "            \"name\": \"jack\",\n" +
        "            \"age\": 0.3\n" +
        "        }\n" +
        "    }\n" +
        "}");
JsonNode node = josson.getNode(
    "animal.map(animals: entries().map(type:key, name:value.name, age:value.age))");
System.out.println(node == null ? null : node.toPrettyString());

Output

{
  "animals" : [ {
    "type" : "dog",
    "name" : "pluto",
    "age" : 4
  }, {
    "type" : "cat",
    "name" : "mini",
    "age" : 1
  }, {
    "type" : "hamster",
    "name" : "jack",
    "age" : 0.3
  } ]
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM