I'm attempting to use Jackson to generate JSON schemas from POJOs. Jackson has two ways to do this. This is the first:
ObjectMapper mapper = new ObjectMapper();
JsonSchema schema = mapper.generateJsonSchema(Entity.class);
String schemaString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema);
This is fine - it generates exactly what you'd expect.
{
"type" : "object",
"properties" : {
"pedigreeIds" : {
"type" : "array",
"items" : {
"type" : "string"
}
},
...
}
}
However, this approach is deprecated in favor of the second, which uses jackson-module-jsonschema:
ObjectMapper mapper = new ObjectMapper();
SchemaFactoryWrapper visitor = new SchemaFactoryWrapper();
mapper.acceptJsonFormatVisitor(mapper.constructType(Entity.class), visitor);
JsonSchema schema = visitor.finalSchema();
String schemaString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema);
Using this code spits out the following for the same entity class:
{
"$ref" : null,
"$schema" : null,
"disallow" : null,
"id" : null,
"required" : null,
"description" : null,
"title" : null,
"enums" : [ ],
"additionalProperties" : null,
"dependencies" : [ ],
"patternProperties" : { },
"properties" : {
"observationTime" : {
"$ref" : null,
"$schema" : null,
"disallow" : null,
...
}
}
}
Given that the first method is deprecated, I'd prefer to use the second if possible. I can't find any differences between what I'm doing and what various code snippets on the internet are doing.
Is there a configuration switch I'm missing, or something I'm simply doing wrong in the second example that causes Jackson to not generate the expected schema?
Related
I am using spring boot and I use a composite key. I want to hide the type of the JSON object.I tried with the annotations like #jsonIgnore, #jsonIgnoreType and nothing works. I have this:
[ {
"consumoId" : {
"inc_acc_id" : "1069931929",
"inc_clu_cellular_number" : "2954316800",
"inc_description" : "Minutes"
},
"inc_frt_id" : null,
"inc_unit" : "Min.",
"inc_amount" : 0.0,
"inc_quantity" : 22.68
}]
and I expect this:
[ {"inc_acc_id" : "1069931929",
"inc_clu_cellular_number" : "2954316800",
"inc_description" : "Minutes" ,
"inc_frt_id" : null,
"inc_unit" : "Min.",
"inc_amount" : 0.0,
"inc_quantity" : 22.68
}]
It looks like you want to inline the properties under the consumoId parent?
#JsonIgnore would skip it altogether, but #JsonUnwrapped will unwrap (omit) the containing object.
Lets say that you have a json array that looks as follows :
[
{
"id" : 1,
"first_name" : "Jane",
"last_name" : "Doe"
},
{
"id" : 2,
"first_name" : "John",
"middle_name" : "Q",
"last_name" : "Public",
"birth_year" : 1971
},
{
"id" : 3,
"anonymous_user" : true,
"crm_id" : "abc123"
},
{
"id" : 4,
"first_name" : "Albert",
"last_name" : "Einstein",
"profession" : "Scientist",
"birth_year" : 1879,
"e_equals_mc_squared" : true
}
]
The goal is to use Jackson to marshal to POJO. My thinking is that I could have a class to contain each K,V pair .. something like :
public class myDataObject {
private String key;
private T value;
...
}
And maybe a container class for that :
public class myDataContainer {
private ArrayList<myDataObject> dataList;
...
}
My question becomes what does marshaling that look like using jackson? There is no schema for the json, each json object can have an unspecified number of K,V pairs and the list of keys is also unspecified.
Does something like this work? Is this even the right approach?
ArrayList<myDataContainer> dataList = mapper.readValue(jsonFile, new TypeReference<ArrayList<myDataContainer>() {});
What your JSON really is, is a list of maps - with Strings as keys and Objects as values.
So, using Jackson, you should be able to do:
ObjectMapper mapper = new ObjectMapper();
List<Map<String, Object>> data = mapper.readValue(json, new TypeReference<List<Map<String, Object>>>(){});
My mongo collection has entries in the following format
{
"myobj" : {
"objList" : [
{ "location" : "Texas" },
{ "location" : "Houston"},
{ "name":"Sam" }
]
},
"category" : "cat1"
}
{
"myobj" :
{
"objList" : [
{ "location" : "Tennesy" },
{ "location" : "NY"},
{ "location" : "SF" }
]
},
"category" : "cat2"
}
I want to extract the "**category**" where location is "Houston". In case of simple JSON object I have to just pass it as query like:
BasicDBObject place = new BasicDBObject();
place.put("location", "Houston");
But in case of nested JSON I don't know how to pass it as a query and get the appropriate category. ie If I pass my location as"Houston" then it should return it's appropriate category "cat1"...i hope my question is clear now....
Ok, you have your documents:
db.coll1.insert({
"myobj" : {
"objList" : [
{ "location" : "Texas" },
{ "location" : "Houston"},
{ "name":"Sam" }
]
},
"category" : "cat1"
})
and
db.coll1.insert({
"myobj" : {
"objList" : [
{ "location" : "Tennesy" },
{ "location" : "Houston"},
{ "location" : "SF" }
]
},
"category" : "cat1"
})
Now you can find what you want using the dot operator:
db.coll1.find({"myobj.objList.location": "Texas"}).pretty() will return one object which has Texas
db.coll1.find({"myobj.objList.location": "SF"}).pretty() will return one object which has SF
db.coll1.find({"myobj.objList.location": "Houston"}).pretty() will return both objects
And now I hope you will be able to write it in Java. I have never used Java, but based on this question you can do something like this. If it will not work, just look how to use dot operator in java driver for mongo:
DBCursor cursor = coll1.find(new BasicDBObject("myobj.objList.location", "Texas"));
P.S. you told, that you wanted to retrieve category. In such a way, you will need to use a projection db.coll1.find({<the query I provided}, {category: 1, _id: 0})
I have a schema like this:
{
"type" : "object",
"$schema" : "http://json-schema.org/draft-03/schema#",
"id" : "urn:jsonschema:com:vlashel:dto:UserDto",
"description" : "this is the top description",
"title" : "this is the top title",
"properties" : {
"number" : {
"type" : "integer"
"required" : true
},
"password" : {
"type" : "string"
"required" : true
}
}
I have the following code that converts this shcema draft 3 to draft 4 by removing "required", I want to collect nodes property names that have 'requred' in them. How do I do that? I don't see methods for this..
JsonNode jsonNode = jsonNodeIterator.next();
ObjectNode element;
if (jsonNode instanceof ObjectNode) {
element = (ObjectNode) jsonNode;
element.remove("required");
String propertyName = element.getPropertyName(); //I'm looking for this kind of method.
Thanks!
You can get all of the nodes that have that property by using the List<JsonNode> findParents(String fieldName), which does that this for you. From the docs:
Method for finding a JSON Object that contains specified field, within
this node or its descendants. If no matching field is found in this
node or its descendants, returns null.
I made a quick example but had to add a few characters to the JSON blob you posted as it is missing some commas and a bracket and can't be read by the ObjectMapper. It is as simple as this:
JsonNode root = mapper.readTree(SCHEMA);
List<JsonNode> required = root.findParents("required");
for (JsonNode node: required) {
Object prettyOutput = mapper.readValue(node, Object.class);
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(prettyOutput));
}
Output:
{
"type" : "integer",
"required" : true
}
{
"type" : "string",
"required" : true
}
Refering to post How to add an array to a MongoDB document using Java?
I have created a mongo schema using java
it has sub elements, I am getting _id for main document
I would like to get _id in sub elements also here output looks (I have marked the portion where I need _id) b.party.find().pretty();
{
"_id" : ObjectId("5399aba6e4b0ae375bfdca88"),
"addressDetails" : [
{
// _id here
"locationName" : "Office",
"phones" : [
{ // _id here
"name" : "Tel1",
"value" : "95253-"
},
{ // _id here
"name" : "Tel2",
"value" : "95253-"
},
{ // _id here
"name" : "Tel3",
"value" : "95253-"
},
{ // _id here
"name" : "Fax1",
"value" : "0253-"
}
],
"address" : "A-3,MIDCA-3,MIDC",
"defaultBillAddrerss" : "",
"pincode" : "422 010",
"city" : null,
"state" : "1",
"country" : ""
},
{ // _id here
"locationName" : "Factory",
"phones" : [
{ // _id here
"name" : "Tel1",
"value" : "0253-"
},
{ // _id here
"name" : "Tel2",
"value" : "0253-"
},
{ // _id here
"name" : "Tel3",
"value" : "0253-"
},
{ // _id here
"name" : "Fax1",
"value" : "0253-"
}
],
"address" : "A-3 INDUSTRIAL AREA,",
"defaultBillAddrerss" : "",
"pincode" : "422 010",
"city" : null,
"state" : "1",
"country" : ""
}
],
"crLimit" : "0.0",
"crPeriod" : "",
"name" : "CROMPTON GREAVES "
}
Java code to create is similar to How to add an array to a MongoDB document using Java?
Is there any code to create ObjectId("") programmatically in java?
To create objectId programmatically, use the following syntax
import org.bson.types.ObjectId;
ObjectId id1 = new ObjectId();
ObjectId id2 = ObjectId.get();
// In case you want to mention the parent ID itself,
ObjectId id3 = new ObjectId("5399aba6e4b0ae375bfdca88");
To create objectId programmatically, use the following syntax
Map<String,String> objectId = new HashMap<String,String>();
objectId.put("$oid","5399aba6e4b0ae375bfdca88");
Then insert into mongodb.