Highly nested json data - java

I have three JSON arrays named item, topping and batter.
Now I want to store this data into single json object. It is highly nested data I don't know how to store data into single object like this.
Resultant object should be like this:
{
"item": [{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batter": [{
"id": "1001",
"type": "Regular"
},
{
"id": "1002",
"type": "Chocolate"
},
{
"id": "1003",
"type": "Blueberry"
},
{
"id": "1004",
"type": "Devil's Food"
}
],
"topping": [{
"id": "5001",
"type": "None"
},
{
"id": "5002",
"type": "Glazed"
},
{
"id": "5005",
"type": "Sugar"
},
{
"id": "5007",
"type": "Powdered Sugar"
},
{
"id": "5006",
"type": "Chocolate with Sprinkles"
},
{
"id": "5003",
"type": "Chocolate"
},
{
"id": "5004",
"type": "Maple"
}
]
},
{
"id": "0002",
"type": "donut",
"name": "Raised",
"ppu": 0.55,
"batter": [{
"id": "1001",
"type": "Regular"
}],
"topping": [{
"id": "5001",
"type": "None"
},
{
"id": "5002",
"type": "Glazed"
},
{
"id": "5005",
"type": "Sugar"
},
{
"id": "5003",
"type": "Chocolate"
},
{
"id": "5004",
"type": "Maple"
}
]
},
{
"id": "0003",
"type": "donut",
"name": "Old Fashioned",
"ppu": 0.55,
"batter": [{
"id": "1001",
"type": "Regular"
},
{
"id": "1002",
"type": "Chocolate"
}
],
"topping": [{
"id": "5001",
"type": "None"
},
{
"id": "5002",
"type": "Glazed"
},
{
"id": "5003",
"type": "Chocolate"
},
{
"id": "5004",
"type": "Maple"
}
]
}
]
}

Related

JOLT shift transformation: filter by inner value of a property (not the name) - only some properties

I am trying to transform a JSON using Jolt transformation looking for some input here.
I am trying to filter by the inner value of the attribute.
My goal is to get an array that contains only the items with the typeName 'xx'. But not all the item object, only some of the fields
{
"id": "11_1",
"action": "add",
"payment": {
"paied": true,
"coin": "dollar"
},
"type": {
"id": "11_1_xx",
"typeName": "xx"
},
"details": {
"place": {
"id": "123",
"name": "xx"
},
"status": {
"id": "123",
"name": "xx"
}
}
}
Here is my input and expected output:
Input:
{
"id": 11,
"item": [
{
"id": "11_1",
"action": "add",
"payment": {
"paied": true,
"coin": "dollar"
},
"type": {
"id": "11_1_xx",
"typeName": "xx",
"typeGroup": "xx",
"typeValue": "xx"
},
"details": {
"place": {
"id": "123",
"name": "xx"
},
"status": {
"id": "123",
"name": "xx"
},
"reason": {
"id": "123",
"name": "xx"
}
},
"item": [
{
"id": "11_1_1",
"action": "add",
"payment": {
"paied": true,
"coin": "dollar"
},
"type": {
"id": "11_1_1_zz",
"typeName": "zz",
"typeGroup": "zz",
"typeValue": "zz"
},
"details": {
"place": {
"id": "123",
"name": "xx"
},
"status": {
"id": "123",
"name": "xx"
},
"reason": {
"id": "123",
"name": "xx"
}
},
"item": [
{
"id": "11_1_1_1",
"action": "add",
"payment": {
"paied": true,
"coin": "NIS"
},
"type": {
"id": "11_1_1_1_xx",
"typeName": "xx",
"typeGroup": "xx",
"typeValue": "xx"
},
"details": {
"place": {
"id": "123",
"name": "xx"
},
"status": {
"id": "123",
"name": "xx"
},
"reason": {
"id": "123",
"name": "xx"
}
}
}
]
},
{
"id": "11_1_2",
"action": "add",
"payment": {
"paied": false,
"coin": "dollar"
},
"type": {
"id": "11_1_2_xx",
"typeName": "xx",
"typeGroup": "xx",
"typeValue": "xx"
},
"details": {
"place": {
"id": "123",
"name": "xx"
},
"status": {
"id": "123",
"name": "xx"
},
"reason": {
"id": "123",
"name": "xx"
}
},
"item": [
{
"id": "11_1_2_1",
"action": "add",
"payment": {
"paied": false,
"coin": "NIS"
},
"type": {
"id": "11_1_2_1_zz",
"typeName": "zz",
"typeGroup": "zz",
"typeValue": "zz"
},
"details": {
"place": {
"id": "123",
"name": "xx"
},
"status": {
"id": "123",
"name": "xx"
},
"reason": {
"id": "123",
"name": "xx"
}
}
}
]
}
]
}
]
}
Expected output:
[
{
"id": "11_1",
"action": "add",
"payment": {
"paied": true,
"coin": "dollar"
},
"type": {
"id": "11_1_xx",
"typeName": "xx"
},
"details": {
"place": {
"id": "123",
"name": "xx"
},
"status": {
"id": "123",
"name": "xx"
}
}
},
{
"id": "11_1_1_1",
"action": "add",
"payment": {
"paied": true,
"coin": "NIS"
},
"type": {
"id": "11_1_1_1_xx",
"typeName": "xx"
},
"details": {
"place": {
"id": "123",
"name": "xx"
},
"status": {
"id": "123",
"name": "xx"
}
}
},
{
"id": "11_1_2",
"action": "add",
"payment": {
"paied": false,
"coin": "dollar"
},
"type": {
"id": "11_1_2_xx",
"typeName": "xx"
},
"details": {
"place": {
"id": "123",
"name": "xx"
},
"status": {
"id": "123",
"name": "xx"
}
}
}
]
Can you please help me to write a simple spec that will do this?
You can use the following explained spec
[
{
// Determine all key-value pairs partitioned under the main value and type.typeValue combinations
"operation": "shift",
"spec": {
"item": {
"*": {
"item": {
"*": {
"item": {
"*": {
"type": {
"#(1,id)": "#(2,id).#(1,typeName).id", //traverse } character twice in order to reach the main id of the object
"#(1,action)": "#(2,id).#(1,typeName).action",
"*": "#(2,id).#(1,typeName).&1.&" // &1 replicates "type" key, & does the leaf value
},
"*": "#(1,id).#(1,type.typeName).&"
}
},
"type": {
"#(1,id)": "#(2,id).#(1,typeName).id",
"#(1,action)": "#(2,id).#(1,typeName).action",
"*": "#(2,id).#(1,typeName).&1.&"
},
"*": "#(1,id).#(1,type.typeName).&"
}
},
"type": {
"#(1,id)": "#(2,id).#(1,typeName).id",
"#(1,action)": "#(2,id).#(1,typeName).action",
"*": "#(2,id).#(1,typeName).&1.&"
},
"*": "#(1,id).#(1,type.typeName).&"
}
}
}
},
{
// Filter out by the desired value(in this case it's "xx")
"operation": "shift",
"spec": {
"*": {
"xx": ""
}
}
},
{
// Get rid of same repeating components of id and action arrays
"operation": "cardinality",
"spec": {
"*": {
"id": "ONE",
"action": "ONE"
}
}
},
{
// Get rid of undesired attributes
"operation": "remove",
"spec": {
"*": {
"type": {
"typeGroup": "",
"typeValue": ""
},
"det*": {
"reason": ""
}
}
}
}
]
You may try library Josson. Function map() build a new ObjectNode. Function field() modify the current ObjectNode and can be used to remove fields. The transformation statement is short and easy to understand.
https://github.com/octomix/josson
Josson josson = Josson.fromJsonString(inputJSON);
JsonNode node = josson.getNode(
"cumulateCollect(" +
" [type.typeName='xx']" + // filter
" .field(type.map(id, typeName)" + // need "type.id" and "type.typeName"
" ,details.field(reason:)" + // remove "details.reason"
" ,item:)" + // remove "item"
" ,item)"); // next round
System.out.println(node.toPrettyString());

will spring-data-rest expose methods in QueryByExampleExecutor interface?

i just learned how to use spring-data-rest to expose methods in repository. i wonder will the spring-data-rest expose methods in QueryByExampleExecutor<T>interface.if not, is there anyway to expose those methods. thx :).
i have a repository class that extend JpaRepository and i did not find any Restful api like methods in QueryByExampleExecutor<T> with resource discovery api.
this is what i got from resource discovery api
{
"alps": {
"version": "1.0",
"descriptor": [
{
"id": "studentEntity-representation",
"href": "http://127.0.0.1:8080/data/profile/studentEntities",
"descriptor": [
{
"name": "name",
"type": "SEMANTIC"
},
{
"name": "age",
"type": "SEMANTIC"
},
{
"name": "height",
"type": "SEMANTIC"
},
{
"name": "weight",
"type": "SEMANTIC"
},
{
"name": "hasPassed",
"type": "SEMANTIC"
}
]
},
{
"id": "create-studentEntities",
"name": "studentEntities",
"type": "UNSAFE",
"descriptor": [],
"rt": "#studentEntity-representation"
},
{
"id": "get-studentEntities",
"name": "studentEntities",
"type": "SAFE",
"descriptor": [
{
"name": "page",
"type": "SEMANTIC",
"doc": {
"format": "TEXT",
"value": "The page to return."
}
},
{
"name": "size",
"type": "SEMANTIC",
"doc": {
"format": "TEXT",
"value": "The size of the page to return."
}
},
{
"name": "sort",
"type": "SEMANTIC",
"doc": {
"format": "TEXT",
"value": "The sorting criteria to use to calculate the content of the page."
}
}
],
"rt": "#studentEntity-representation"
},
{
"id": "delete-studentEntity",
"name": "studentEntity",
"type": "IDEMPOTENT",
"descriptor": [],
"rt": "#studentEntity-representation"
},
{
"id": "update-studentEntity",
"name": "studentEntity",
"type": "IDEMPOTENT",
"descriptor": [],
"rt": "#studentEntity-representation"
},
{
"id": "get-studentEntity",
"name": "studentEntity",
"type": "SAFE",
"descriptor": [],
"rt": "#studentEntity-representation"
},
{
"id": "patch-studentEntity",
"name": "studentEntity",
"type": "UNSAFE",
"descriptor": [],
"rt": "#studentEntity-representation"
}
]
}
}

read a json file from ibm bluemix personality insights and convert into objects in java

Trying to sort out a JSON file retrieved by IBM bluemix personality insight so that I can display the results like.
Personality: Adventurousness = 0.6317251869427992%;
Personality: Artistic interests = 0.9994303217024612%;
etc.
Trying to use Gson to pass variables from JSON file but not working. Is There a better way of doing this or is Gson still a good way of parsing the elements from a JSON file. Also the JSON file I am using is created below:
{
"id": "*UNKNOWN*",
"processed_lang": "en",
"source": "*UNKNOWN*",
"tree": {
"children": [
{
"children": [
{
"category": "personality",
"children": [
{
"category": "personality",
"children": [
{
"category": "personality",
"id": "Adventurousness",
"name": "Adventurousness",
"percentage": 0.6317251869427992,
"sampling_error": 0.0550028572
},
{
"category": "personality",
"id": "Artistic interests",
"name": "Artistic interests",
"percentage": 0.9994303217024612,
"sampling_error": 0.1112535152
},
{
"category": "personality",
"id": "Emotionality",
"name": "Emotionality",
"percentage": 0.9110319825845377,
"sampling_error": 0.0517194892
},
{
"category": "personality",
"id": "Imagination",
"name": "Imagination",
"percentage": 0.9563652127187121,
"sampling_error": 0.0692827052
},
{
"category": "personality",
"id": "Intellect",
"name": "Intellect",
"percentage": 0.9993135468190391,
"sampling_error": 0.0609848988
},
{
"category": "personality",
"id": "Liberalism",
"name": "Authority-challenging",
"percentage": 0.9992476810581103,
"sampling_error": 0.0889871444
}
],
"id": "Openness",
"name": "Openness",
"percentage": 0.9846019609615686,
"sampling_error": 0.0659049028
},
{
"category": "personality",
"children": [
{
"category": "personality",
"id": "Achievement striving",
"name": "Achievement striving",
"percentage": 0.48216415575634164,
"sampling_error": 0.1055280664
},
{
"category": "personality",
"id": "Cautiousness",
"name": "Cautiousness",
"percentage": 0.9645239970907649,
"sampling_error": 0.0975392952
},
{
"category": "personality",
"id": "Dutifulness",
"name": "Dutifulness",
"percentage": 0.48295582786617886,
"sampling_error": 0.067074676
},
{
"category": "personality",
"id": "Orderliness",
"name": "Orderliness",
"percentage": 0.8923116642953849,
"sampling_error": 0.0750867144
},
{
"category": "personality",
"id": "Self-discipline",
"name": "Self-discipline",
"percentage": 0.12761071487631187,
"sampling_error": 0.0507461328
},
{
"category": "personality",
"id": "Self-efficacy",
"name": "Self-efficacy",
"percentage": 0.47236420942319157,
"sampling_error": 0.0984568308
}
],
"id": "Conscientiousness",
"name": "Conscientiousness",
"percentage": 0.20312039774513813,
"sampling_error": 0.0823480716
},
{
"category": "personality",
"children": [
{
"category": "personality",
"id": "Activity level",
"name": "Activity level",
"percentage": 0.3721671469083689,
"sampling_error": 0.0837163552
},
{
"category": "personality",
"id": "Assertiveness",
"name": "Assertiveness",
"percentage": 0.3608814928456784,
"sampling_error": 0.0891259996
},
{
"category": "personality",
"id": "Cheerfulness",
"name": "Cheerfulness",
"percentage": 0.168558437901277,
"sampling_error": 0.1118533964
},
{
"category": "personality",
"id": "Excitement-seeking",
"name": "Excitement-seeking",
"percentage": 0.526708697277564,
"sampling_error": 0.0853730664
},
{
"category": "personality",
"id": "Friendliness",
"name": "Outgoing",
"percentage": 0.27834657828325515,
"sampling_error": 0.0804874488
},
{
"category": "personality",
"id": "Gregariousness",
"name": "Gregariousness",
"percentage": 0.15285819617130203,
"sampling_error": 0.0618727368
}
],
"id": "Extraversion",
"name": "Extraversion",
"percentage": 0.3684311825466099,
"sampling_error": 0.0617198188
},
{
"category": "personality",
"children": [
{
"category": "personality",
"id": "Altruism",
"name": "Altruism",
"percentage": 0.5198409884448938,
"sampling_error": 0.0760231772
},
{
"category": "personality",
"id": "Cooperation",
"name": "Cooperation",
"percentage": 0.8204615138656874,
"sampling_error": 0.0845446968
},
{
"category": "personality",
"id": "Modesty",
"name": "Modesty",
"percentage": 0.3028236905698857,
"sampling_error": 0.0608841808
},
{
"category": "personality",
"id": "Morality",
"name": "Uncompromising",
"percentage": 0.3683263428886422,
"sampling_error": 0.067562902
},
{
"category": "personality",
"id": "Sympathy",
"name": "Sympathy",
"percentage": 0.9458613463480976,
"sampling_error": 0.1038568852
},
{
"category": "personality",
"id": "Trust",
"name": "Trust",
"percentage": 0.8915942559871681,
"sampling_error": 0.0624363272
}
],
"id": "Agreeableness",
"name": "Agreeableness",
"percentage": 0.07292135773434255,
"sampling_error": 0.10250565
},
{
"category": "personality",
"children": [
{
"category": "personality",
"id": "Anger",
"name": "Fiery",
"percentage": 0.02340275040082851,
"sampling_error": 0.0999794916
},
{
"category": "personality",
"id": "Anxiety",
"name": "Prone to worry",
"percentage": 0.39598631299245396,
"sampling_error": 0.0596402444
},
{
"category": "personality",
"id": "Depression",
"name": "Melancholy",
"percentage": 0.3929152963217911,
"sampling_error": 0.06402023080000001
},
{
"category": "personality",
"id": "Immoderation",
"name": "Immoderation",
"percentage": 0.6895235350576241,
"sampling_error": 0.057768048
},
{
"category": "personality",
"id": "Self-consciousness",
"name": "Self-consciousness",
"percentage": 0.5331328944254717,
"sampling_error": 0.0617367476
},
{
"category": "personality",
"id": "Vulnerability",
"name": "Susceptible to stress",
"percentage": 0.16507939784505093,
"sampling_error": 0.09147593000000001
}
],
"id": "Neuroticism",
"name": "Emotional range",
"percentage": 0.5734234749195765,
"sampling_error": 0.097180016
}
],
"id": "Openness_parent",
"name": "Openness",
"percentage": 0.9846019609615686
}
],
"id": "personality",
"name": "Big 5"
},
{
"children": [
{
"category": "needs",
"children": [
{
"category": "needs",
"id": "Challenge",
"name": "Challenge",
"percentage": 0.2163701166672924,
"sampling_error": 0.088382552
},
{
"category": "needs",
"id": "Closeness",
"name": "Closeness",
"percentage": 0.31761617269156583,
"sampling_error": 0.08715462160000001
},
{
"category": "needs",
"id": "Curiosity",
"name": "Curiosity",
"percentage": 0.9247945752958546,
"sampling_error": 0.1257142204
},
{
"category": "needs",
"id": "Excitement",
"name": "Excitement",
"percentage": 0.29876054433673094,
"sampling_error": 0.1150890848
},
{
"category": "needs",
"id": "Harmony",
"name": "Harmony",
"percentage": 0.5632884023172972,
"sampling_error": 0.115445782
},
{
"category": "needs",
"id": "Ideal",
"name": "Ideal",
"percentage": 0.11175906677024067,
"sampling_error": 0.10459386120000001
},
{
"category": "needs",
"id": "Liberty",
"name": "Liberty",
"percentage": 0.15242136815334956,
"sampling_error": 0.1516857684
},
{
"category": "needs",
"id": "Love",
"name": "Love",
"percentage": 0.5300501971205276,
"sampling_error": 0.1061716772
},
{
"category": "needs",
"id": "Practicality",
"name": "Practicality",
"percentage": 0.2652581576775723,
"sampling_error": 0.0925707984
},
{
"category": "needs",
"id": "Self-expression",
"name": "Self-expression",
"percentage": 0.4226113277009137,
"sampling_error": 0.0858659712
},
{
"category": "needs",
"id": "Stability",
"name": "Stability",
"percentage": 0.39124496873185977,
"sampling_error": 0.11233243080000001
},
{
"category": "needs",
"id": "Structure",
"name": "Structure",
"percentage": 0.082319764233448,
"sampling_error": 0.0845231684
}
],
"id": "Curiosity_parent",
"name": "Curiosity",
"percentage": 0.9247945752958546
}
],
"id": "needs",
"name": "Needs"
},
{
"children": [
{
"category": "values",
"children": [
{
"category": "values",
"id": "Conservation",
"name": "Conservation",
"percentage": 0.02758870597873586,
"sampling_error": 0.0718139704
},
{
"category": "values",
"id": "Openness to change",
"name": "Openness to change",
"percentage": 0.7985238196496101,
"sampling_error": 0.06952367
},
{
"category": "values",
"id": "Hedonism",
"name": "Hedonism",
"percentage": 0.5013608564027453,
"sampling_error": 0.14348115520000002
},
{
"category": "values",
"id": "Self-enhancement",
"name": "Self-enhancement",
"percentage": 0.14340520219382769,
"sampling_error": 0.10937856280000001
},
{
"category": "values",
"id": "Self-transcendence",
"name": "Self-transcendence",
"percentage": 0.45891860839197324,
"sampling_error": 0.08747207800000001
}
],
"id": "Conservation_parent",
"name": "Conservation",
"percentage": 0.02758870597873586
}
],
"id": "values",
"name": "Values"
}
],
"id": "r",
"name": "root"
},
"word_count": 104,
"word_count_message": "There were 104 words in the input. We need a minimum of 600, preferably 1,200 or more, to compute statistically significant estimates"
}
I would recommend using the Watson Developer Cloud Java SDK, it does this mapping for you. It provides a Java object wrapping the Personality Insights result. See https://github.com/watson-developer-cloud/java-sdk/tree/master/personality-insights#usage

Elasticsearch:Getting nested object under path is not of nested type

I am new to the Elastic search world.Basically I am trying to retrieve the nested objects based on the ID.This is the JSON representation of my document.
{
"_index": "xyz",
"_type": "abc",
"_id": "12",
"_version": 1,
"found": true,
"_source":
{
"lastModifiedBy": "12",
"lastModifiedDate": "2015-12-31T19:45:29.493Z",
"profile":
[
{
"type": "nested",
"views":
[
{
"type": "nested",
"id": "view1",
"name": "view1",
"properties":
[
{
"name": "default",
"value": false
}
],
"widgets":
[
{
"type": "nested",
"id": "graph",
"name": "graph",
"elementId": "ui_graph",
"properties":
[
{
"name": "currency",
"value": "YEN"
}
]
}
]
}
} ] } ]
I am trying to get the widgets based on the view id.This is the my search query.
"query" : {
"term" : {
"_id" : "12"
}
},
"post_filter" : {
"nested" : {
"query" : {
"filtered" : {
"query" : {
"match_all" : { }
},
"filter" : {
"term" : {
"profile.views.id" : "view1"
}
}
}
},
"path" : "profile.views"
}
}
}
I am not sure what is wrong here.But getting "nested object under path [profile.views] is not of nested type]".
Below is my mapping structure
{
"xyz": {
"mappings": {
"abc": {
"properties": {
"lastModifiedBy": {
"type": "string"
},
"lastModifiedDate": {
"type": "date",
"format": "dateOptionalTime"
},
"name": {
"type": "string"
},
"profile": {
"properties": {
"lastModifiedBy": {
"type": "string"
},
"lastModifiedDate": {
"type": "date",
"format": "dateOptionalTime"
},
"type": {
"type": "string"
},
"views": {
"properties": {
"id": {
"type": "string"
},
"isDefault": {
"type": "boolean"
},
"name": {
"type": "string"
},
"properties": {
"properties": {
"name": {
"type": "string"
},
"type": {
"type": "string"
},
"value": {
"type": "string"
}
}
},
"type": {
"type": "string"
},
"viewId": {
"type": "string"
},
"widgets": {
"properties": {
"elementId": {
"type": "string"
},
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"properties": {
"properties": {
"name": {
"type": "string"
},
"type": {
"type": "string"
},
"value": {
"type": "string"
}
}
},
"type": {
"type": "string"
}
}
}
}
}
}
}
}
}
}
}
}
Please help!
You are getting the error because you have not specified type as nested for profile and views. Refer to the Docs for how to created nested objects . You should be defining type as nested for every nested object like this
{
"xyz": {
"mappings": {
"abc": {
"properties": {
"lastModifiedBy": {
"type": "string"
},
"lastModifiedDate": {
"type": "date",
"format": "dateOptionalTime"
},
"name": {
"type": "string"
},
"profile": {
"type": "nested", <--- here, you need this for every nested object
"properties": {
"lastModifiedBy": {
"type": "string"
},
"lastModifiedDate": {
"type": "date",
"format": "dateOptionalTime"
},
"type": {
"type": "string"
},
"views": {
"type": "nested",
"properties": {
"id": {
"type": "string"
},
"isDefault": {
"type": "boolean"
},
"name": {
"type": "string"
},
"properties": {
"type": "nested",
"properties": {
"name": {
"type": "string"
},
"type": {
"type": "string"
},
"value": {
"type": "string"
}
}
},
"type": {
"type": "string"
},
"viewId": {
"type": "string"
},
"widgets": {
"type": "nested",
"properties": {
"elementId": {
"type": "string"
},
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"properties": {
"type": "nested",
"properties": {
"name": {
"type": "string"
},
"type": {
"type": "string"
},
"value": {
"type": "string"
}
}
},
"type": {
"type": "string"
}
}
}
}
}
}
}
}
}
}
}
}
Hope this helps!!

jsonschema2pojo with URL doesn't works

I have problems with using jsonschema2pojo in my code.
So, I use jsonschema2pojo generator(http://www.jsonschema2pojo.org/) to generate POJO's from this URL: http://store.steampowered.com/api/appdetails/?appids=10
Finally, I create all these class in one package 'model'.
Then in I try use it to read json from link but I receive exception:
Exception in thread "main" java.lang.NullPointerException
at controller.View.main(View.java:26)
I don't understand why.
Here is code How I can do it:
public class View {
private static String urlStr = "http://store.steampowered.com/api/appdetails/?appids=10";
public static void main(String[] args) {
ObjectMapper objectMapper = new ObjectMapper();
try {
Game game = objectMapper.readValue(new URL(urlStr), Game.class);
System.out.println(game.getData().getName());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (JsonParseException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The Game.class is finall class which I set in generator as 'Class name'.
What is wrong? How can I get all these data from this link?
In maven I configure it like that:
<plugin>
<groupId>org.jsonschema2pojo</groupId>
<artifactId>jsonschema2pojo-maven-plugin</artifactId>
<version>0.4.18</version>
<configuration>
<sourceType>jsonschema</sourceType>
<outputEncoding>${project.build.sourceEncoding}</outputEncoding>
<outputDirectory>${project.build.directory}/generated-sources</outputDirectory>
<annotationStyle>jackson2</annotationStyle>
<generateBuilders>true</generateBuilders>
<initializeCollections>true</initializeCollections>
</configuration>
<executions>
<execution>
<id>generate-game</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<targetPackage>model.game</targetPackage>
<sourceDirectory>${basedir}/src/main/resources/schema/game</sourceDirectory>
</configuration>
</execution>
</executions>
</plugin>
As I said, all classes are in src/main/java and package 'model', my schema is in sr/main/resources/schema/ in file 'game'
And my schema looks like:
{
"type": "object",
"required":false,
"javaType":"model.Game",
"properties": {
"10": {
"id": "10",
"type": "object",
"properties": {
"success": {
"id": "success",
"type": "boolean"
},
"data": {
"id": "data",
"type": "object",
"properties": {
"type": {
"id": "type",
"type": "string"
},
"name": {
"id": "name",
"type": "string"
},
"steam_appid": {
"id": "steam_appid",
"type": "integer"
},
"required_age": {
"id": "required_age",
"type": "integer"
},
"is_free": {
"id": "is_free",
"type": "boolean"
},
"detailed_description": {
"id": "detailed_description",
"type": "string"
},
"about_the_game": {
"id": "about_the_game",
"type": "string"
},
"supported_languages": {
"id": "supported_languages",
"type": "string"
},
"header_image": {
"id": "header_image",
"type": "string"
},
"website": {
"id": "website",
"type": "null"
},
"pc_requirements": {
"id": "pc_requirements",
"type": "object",
"properties": {
"minimum": {
"id": "minimum",
"type": "string"
}
}
},
"mac_requirements": {
"id": "mac_requirements",
"type": "object",
"properties": {
"minimum": {
"id": "minimum",
"type": "string"
}
}
},
"linux_requirements": {
"id": "linux_requirements",
"type": "object",
"properties": {
"minimum": {
"id": "minimum",
"type": "string"
}
}
},
"developers": {
"id": "developers",
"type": "array",
"items": {
"id": "0",
"type": "string"
}
},
"publishers": {
"id": "publishers",
"type": "array",
"items": {
"id": "0",
"type": "string"
}
},
"price_overview": {
"id": "price_overview",
"type": "object",
"properties": {
"currency": {
"id": "currency",
"type": "string"
},
"initial": {
"id": "initial",
"type": "integer"
},
"final": {
"id": "final",
"type": "integer"
},
"discount_percent": {
"id": "discount_percent",
"type": "integer"
}
}
},
"packages": {
"id": "packages",
"type": "array",
"items": [
{
"id": "0",
"type": "string"
},
{
"id": "1",
"type": "integer"
},
{
"id": "2",
"type": "integer"
},
{
"id": "3",
"type": "integer"
}
]
},
"package_groups": {
"id": "package_groups",
"type": "array",
"items": {
"id": "0",
"type": "object",
"properties": {
"name": {
"id": "name",
"type": "string"
},
"title": {
"id": "title",
"type": "string"
},
"description": {
"id": "description",
"type": "string"
},
"selection_text": {
"id": "selection_text",
"type": "string"
},
"save_text": {
"id": "save_text",
"type": "string"
},
"display_type": {
"id": "display_type",
"type": "integer"
},
"is_recurring_subscription": {
"id": "is_recurring_subscription",
"type": "string"
},
"subs": {
"id": "subs",
"type": "array",
"items": [
{
"id": "0",
"type": "object",
"properties": {
"packageid": {
"id": "packageid",
"type": "string"
},
"percent_savings_text": {
"id": "percent_savings_text",
"type": "string"
},
"percent_savings": {
"id": "percent_savings",
"type": "integer"
},
"option_text": {
"id": "option_text",
"type": "string"
},
"option_description": {
"id": "option_description",
"type": "string"
},
"can_get_free_license": {
"id": "can_get_free_license",
"type": "string"
},
"is_free_license": {
"id": "is_free_license",
"type": "boolean"
},
"price_in_cents_with_discount": {
"id": "price_in_cents_with_discount",
"type": "integer"
}
}
},
{
"id": "1",
"type": "object",
"properties": {
"packageid": {
"id": "packageid",
"type": "integer"
},
"percent_savings_text": {
"id": "percent_savings_text",
"type": "string"
},
"percent_savings": {
"id": "percent_savings",
"type": "integer"
},
"option_text": {
"id": "option_text",
"type": "string"
},
"option_description": {
"id": "option_description",
"type": "string"
},
"can_get_free_license": {
"id": "can_get_free_license",
"type": "string"
},
"is_free_license": {
"id": "is_free_license",
"type": "boolean"
},
"price_in_cents_with_discount": {
"id": "price_in_cents_with_discount",
"type": "integer"
}
}
},
{
"id": "2",
"type": "object",
"properties": {
"packageid": {
"id": "packageid",
"type": "integer"
},
"percent_savings_text": {
"id": "percent_savings_text",
"type": "string"
},
"percent_savings": {
"id": "percent_savings",
"type": "integer"
},
"option_text": {
"id": "option_text",
"type": "string"
},
"option_description": {
"id": "option_description",
"type": "string"
},
"can_get_free_license": {
"id": "can_get_free_license",
"type": "string"
},
"is_free_license": {
"id": "is_free_license",
"type": "boolean"
},
"price_in_cents_with_discount": {
"id": "price_in_cents_with_discount",
"type": "integer"
}
}
},
{
"id": "3",
"type": "object",
"properties": {
"packageid": {
"id": "packageid",
"type": "integer"
},
"percent_savings_text": {
"id": "percent_savings_text",
"type": "string"
},
"percent_savings": {
"id": "percent_savings",
"type": "integer"
},
"option_text": {
"id": "option_text",
"type": "string"
},
"option_description": {
"id": "option_description",
"type": "string"
},
"can_get_free_license": {
"id": "can_get_free_license",
"type": "string"
},
"is_free_license": {
"id": "is_free_license",
"type": "boolean"
},
"price_in_cents_with_discount": {
"id": "price_in_cents_with_discount",
"type": "integer"
}
}
}
]
}
}
}
},
"platforms": {
"id": "platforms",
"type": "object",
"properties": {
"windows": {
"id": "windows",
"type": "boolean"
},
"mac": {
"id": "mac",
"type": "boolean"
},
"linux": {
"id": "linux",
"type": "boolean"
}
}
},
"metacritic": {
"id": "metacritic",
"type": "object",
"properties": {
"score": {
"id": "score",
"type": "integer"
},
"url": {
"id": "url",
"type": "string"
}
}
},
"categories": {
"id": "categories",
"type": "array",
"items": [
{
"id": "0",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"description": {
"id": "description",
"type": "string"
}
}
},
{
"id": "1",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"description": {
"id": "description",
"type": "string"
}
}
}
]
},
"genres": {
"id": "genres",
"type": "array",
"items": {
"id": "0",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "string"
},
"description": {
"id": "description",
"type": "string"
}
}
}
},
"screenshots": {
"id": "screenshots",
"type": "array",
"items": [
{
"id": "0",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "1",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "2",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "3",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "4",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "5",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "6",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "7",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "8",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "9",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "10",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "11",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "12",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
}
]
},
"recommendations": {
"id": "recommendations",
"type": "object",
"properties": {
"total": {
"id": "total",
"type": "integer"
}
}
},
"achievements": {
"id": "achievements",
"type": "object",
"properties": {
"total": {
"id": "total",
"type": "integer"
}
}
},
"release_date": {
"id": "release_date",
"type": "object",
"properties": {
"coming_soon": {
"id": "coming_soon",
"type": "boolean"
},
"date": {
"id": "date",
"type": "string"
}
}
},
"support_info": {
"id": "support_info",
"type": "object",
"properties": {
"url": {
"id": "url",
"type": "string"
},
"email": {
"id": "email",
"type": "string"
}
}
},
"background": {
"id": "background",
"type": "string"
}
}
}
},
"required": [
"success",
"data",
"id",
"path_thumbnail",
"path_full"
]
}
},
"required": [
"10"
]
}
With this config I can read all data using this line instead of before System.out.println:
System.out.println( objectMapper.writeValueAsString( game ) );
Now I can see full json string, but how can I read it using 'game.getData().getName()' etc ?
The JSON schema that you gave defines "10" as a top-level property containing everything else.
{
"type": "object",
"required":false,
"javaType":"model.Game",
"properties": {
"10": {
"id": "10",
"type": "object",
"properties": {
"success": {
"id": "success",
"type": "boolean"
},
"data": {
"id": "data",
"type": "object",
"properties": {
"type": {
"id": "type",
"type": "string"
},
"name": {
"id": "name",
"type": "string"
},
...
jsonschema2pojo reads that schema and generates a class named _10 as part of the model. You can find this in _10.java in the generated-sources directory.
#JsonInclude(JsonInclude.Include.NON_NULL)
#Generated("org.jsonschema2pojo")
#JsonPropertyOrder({
"success",
"data"
})
public class _10 {
I don't know if this was intentional in the schema. If it's intentional, then you would need to access the name like this.
System.out.println(game.get10().getData().getName());
I was able to get it working after making that change.
EDIT: It appears these JSON messages are expected to have a variable ID as a top-level key containing everything else, so we need to handle this a bit differently. We can generalize the schema so that it isn't specific to a particular ID, and then we can use a two-step process to parse the message. First, we'll use [ObjectMapper#readValue](https://fasterxml.github.io/jackson-databind/javadoc/2.5/com/fasterxml/jackson/databind/ObjectMapper.html#readValue(java.net.URL, com.fasterxml.jackson.core.type.TypeReference)) to parse the whole message into a Map<String, Object>. We expect that top-level map will contain a single element, corresponding to the ID of the document we requested, and its value will be a sub-map containing the values we're interested in. We'll then pass that sub-map through [ObjectMapper#convertValue](https://fasterxml.github.io/jackson-databind/javadoc/2.5/com/fasterxml/jackson/databind/ObjectMapper.html#convertValue(java.lang.Object, java.lang.Class)) to get the Game object that we want.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cnauroth</groupId>
<artifactId>test-json</artifactId>
<packaging>jar</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>Test JSON</name>
<description>Test JSON</description>
<build>
<plugins>
<plugin>
<groupId>org.jsonschema2pojo</groupId>
<artifactId>jsonschema2pojo-maven-plugin</artifactId>
<version>0.4.18</version>
<configuration>
<sourceType>jsonschema</sourceType>
<outputEncoding>${project.build.sourceEncoding}</outputEncoding>
<outputDirectory>${project.build.directory}/generated-sources/java</outputDirectory>
<annotationStyle>jackson2</annotationStyle>
<generateBuilders>true</generateBuilders>
<initializeCollections>true</initializeCollections>
</configuration>
<executions>
<execution>
<id>generate-game</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<targetPackage>model.game</targetPackage>
<sourceDirectory>${basedir}/src/main/resources/schema/game</sourceDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<mainClass>View</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>${project.artifactId}</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
</project>
game
The JSON schema file is too large to paste, so here is a link to a gist.
View.java
import java.net.URI;
import java.util.Map;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import model.Game;
public class View {
public static void main(String[] args) throws Exception {
String id = args[0];
URI uri = new URI("http", "store.steampowered.com", "/api/appdetails",
"appids=" + id, null);
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> obj = objectMapper.readValue(uri.toURL(),
new TypeReference<Map<String, Object>>(){});
Game game = objectMapper.convertValue(obj.get(id), Game.class);
System.out.println(game.getData().getName());
}
}
Demo
> mvn clean package
> java -jar target/test-json.jar 10
Counter-Strike
> java -jar target/test-json.jar 219
Half-Life 2: Demo
Additionally, I needed to make one other change to the schema. I removed the linux_requirements property. This is because looking at document 10 vs. document 219, it's an object in the former and it's an array in the latter. For document 219, the parser didn't know how to make sense of the array, because we were expecting an object. It's odd for data returned from an API to be inconsistent like this. You might need to do some more tinkering with the schema to get this fully working for all possible JSON documents returned from that API.
I have put all of the code into a GitHub repository. You can take that code, build it and run it to see it working. Then, you can adapt it further to your needs.
Instead of trying to model the object containing the ids with properties, use additionalProperties. Assuming that the top level type contains several games, you could try replacing
{
"type": "object",
"required":false,
"javaType":"model.Game",
"properties": {
"10": {
"id": "10",
"type": "object",
...
}
}
}
with something like
{
"type": "object",
"required":false,
"javaType":"model.Games",
"additionalProperties": {
"id": "game",
"type": "object",
"javaType": "model.Game"
...
}
}
This should make a model.Games type with a method like public Map<String, Game> getAdditionalProperties().

Categories