How can i parse JSON from Webservice result with Gson - json

When i send request to server.
I get result data with this format:
{
"menu": {
"7": [{
"m_id": "1",
"m_flag": "1",
"m_type": "7",
"m_name": "\u30cf\u30a4\u30cd\u30b1\u30f3",
"m_price": "1000",
"m_cost": "158",
"m_regist_date": "0000-00-00",
"p_id": "0"
}, {
"m_id": "2",
"m_flag": "1",
"m_type": "7",
"m_name": "\u30ae\u30cd\u30b9",
"m_price": "1000",
"m_cost": "250",
"m_regist_date": "0000-00-00",
"p_id": "0"
},....
"2": [{
"m_id": "149",
"m_flag": "1",
"m_type": "2",
"m_name": "\u30da\u30fc\u30bf\u30fc\u30e4\u30b3\u30d6\u30ea\u30fc\u30b9\u30ea\u30f3\u30b0",
"m_price": "6500",
"m_cost": "2100",
"m_regist_date": "0000-00-00",
"p_id": "0"
}, {
"m_id": "150",
"m_flag": "1",
"m_type": "2",
"m_name": "\u30a4\u30d3\u30b9\u30af\u30b9 \u30eb\u30fc\u30b8\u30e5 08",
"m_price": "6800",
"m_cost": "2520",
"m_regist_date": "0000-00-00",
"p_id": "0"
},...
}
It very long . So when i used :
JSONObject json = jsonParser.makeHttpRequest(REQUEST_URL, "POST",params);
menu = json.getJSONArray("menu");
I get error and can't get data of JSON:
Error parsing data org.json.JSONException: End of input at character 0 of
How can i Parse data of json , I do not know how to use Gson.
AND how can i get data of KEY "2".
Thank you very much!

If you are looking for GSON parsing then find it here.
Simply create a POJO class and map it to JSON string.
Sample code:
class MenuDetail {
private String m_id;
private String m_flag;
private String m_type;
private String m_name;
private String m_price;
private String m_cost;
private String m_regist_date;
private String p_id;
// getter & setter
}
...
Type type = new TypeToken<Map<String, Map<String, ArrayList<MenuDetail>>>>() {}.getType();
Map<String, Map<String, ArrayList<MenuDetail>>> data = new Gson().fromJson(json, type);
System.out.println(new GsonBuilder().setPrettyPrinting().create().toJson(data));
output:
{
"menu": {
"7": [
{
"m_id": "1",
"m_flag": "1",
"m_type": "7",
"m_name": "name",
"m_price": "1000",
"m_cost": "158",
"m_regist_date": "0000-00-00",
"p_id": "0"
},
{
"m_id": "2",
"m_flag": "1",
"m_type": "7",
"m_name": "name",
"m_price": "1000",
"m_cost": "250",
"m_regist_date": "0000-00-00",
"p_id": "0"
}
]
}
}

Related

Filter JSON output with regex (or JSONSlurper?)

Trying to achieve this by using the following script, which I want to extend with a loop to loop through the input. This should filter on the objects with have the value "valse", the others should be deleted/replaced.
def Message processData(Message message) {
//getBody & new jsonSlurper
def body = message.getBody(java.lang.String) as String
def data = new JsonSlurper().parseText(body)
if (data.value != "false") {
body = body.replaceAll(~/^(.*?)\childNodes/, "")
message.setBody(body);
} else {
}
return message
}
Input:
[{
"name": "1",
"value": "true",
"childNodes": [{
"name": "2",
"value": "true",
"childNodes": [{
"name": "3",
"value": "false",
"childNodes": [{
"name": "4",
"value": "false"
}]
}]
}]
}]
Desired output:
[{
"name": "3",
"value": "false",
"childNodes": [{
"name": "4",
"value": "false"
}]
}]
import groovy.json.*
def body ='''
[{
"name": "1",
"value": "true",
"childNodes": [{
"name": "2",
"value": "true",
"childNodes": [{
"name": "3",
"value": "false",
"childNodes": [{
"name": "4",
"value": "false"
}]
}]
}]
}]
'''
def filter(arr){
for(i in arr){
if(i.value == 'false') return [i]
def filteredChild = filter(i.childNodes)
if(filteredChild)return filteredChild
}
return null // not found
}
def filtered = filter( new JsonSlurper().parseText(body) )
println new JsonBuilder(filtered).toPrettyString()
Assuming you have only a single child object every time and that your task is finding the first value=false node and returning it with all the child nodes, you can do the following:
def processData(String message) {
def data = new JsonSlurper().parseText(message)[0]
while (data.value != 'false') { data = data.childNodes[0] }
return new JsonBuilder([data]).toPrettyString()
}
Here's a Spock test to go with it (replaced pretty string with regular json string so that it's easier to compare strings with ==)
class ParseSpec extends Specification {
def testString = '''
[{
"name": "1",
"value": "true",
"childNodes": [{
"name": "2",
"value": "true",
"childNodes": [{
"name": "3",
"value": "false",
"childNodes": [{
"name": "4",
"value": "false"
}]
}]
}]
}]
'''
def processData(String message) {
def data = new JsonSlurper().parseText(message)[0]
while (data.value != 'false') { data = data.childNodes[0] }
return JsonOutput.toJson([data])
}
def 'run test'() {
expect:
'''[{"name":"3","value":"false","childNodes":[{"name":"4","value":"false"}]}]''' == processData(testString)
}
}

Map JSON field values to data class values

I'm getting a JSON string that I'd like to clean up a bit and return less data. However, I'm having trouble figuring out how to get the values from the JSON and properly attach it to a data class I've created.
Here is the incoming JSON:
{
"continent": {
"code": "EU",
"names": {
"de": "Europa",
"ru": "Европа",
"pt-BR": "Europa",
"ja": "ヨーロッパ",
"en": "Europe",
"fr": "Europe",
"zh-CN": "欧洲",
"es": "Europa"
},
"geoname_id": 6255148
},
"country": {
"is_in_european_union": true,
"names": {
"de": "Frankreich",
"ru": "Франция",
"pt-BR": "França",
"ja": "フランス共和国",
"en": "France",
"fr": "France",
"zh-CN": "法国",
"es": "Francia"
},
"iso_code": "FR",
"geoname_id": 3017382
},
"city": {
"geoname_id": 2977058,
"names": {
"en": "Saint-Saulve",
"ru": "Сен-Сольв",
"zh-CN": "圣索尔沃"
}
},
"location": {
"accuracy_radius": 10,
"time_zone": "Europe/Paris",
"latitude": 50.3714,
"longitude": 3.5561
},
"postal": {
"code": "59880"
},
"registered_country": {
"is_in_european_union": true,
"names": {
"de": "Frankreich",
"ru": "Франция",
"pt-BR": "França",
"ja": "フランス共和国",
"en": "France",
"fr": "France",
"zh-CN": "法国",
"es": "Francia"
},
"iso_code": "FR",
"geoname_id": 3017382
},
"subdivisions": [
{
"names": {
"fr": "Hauts-de-France",
"en": "Hauts-de-France"
},
"iso_code": "HDF",
"geoname_id": 11071624
},
{
"names": {
"de": "Nord",
"en": "North",
"fr": "Nord",
"es": "Norte"
},
"iso_code": "59",
"geoname_id": 2990129
}
]
}
Data Classes:
data class locationData(val accuracyRadius: String = "", val timeZone: String = "", val latitude: String = "",
val longitude: String = "", val postalCode: String = "", val continent: Continent,
val country: Country, val city: City, val subdivision: Subdivision)
data class Continent(val code: String = "", val name: String = "", val geonameId: String = "")
data class Country(val isEU: Boolean = false, val name: String = "", val isoCode: String = "", val geonameId: String = "")
data class City(val name: String = "", val geonameId: String = "")
data class Subdivision(val name: String = "", val isoCode: String = "", val geonameId: String = "")
My sad attempt at iterating through the json and filtering out the pieces I don't want:
private fun cleanData(data: JsonNode): String {
data.fieldNames().forEachRemaining { field ->
println(field);
}
val result = data.filter { item ->
if (item.has("names")) {
return item.get("names").has("en"); item["name"] = item.get("names").get("en");
}
return item.toString();
}
return "";
/*val continent = {
"code" = data.get("continent").get("code"),
}*/
}
This is what my desired JSON output should be:
{
"accuracy_radius": 10,
"time_zone": "Europe/Paris",
"latitude": 50.3714,
"longitude": 3.5561,
"postalCode": "59880",
"continent": {
"code": "EU",
"name": "Europe",
"geonameId": 6255148
},
"country": {
"isEU": true,
"name": "France",
"isoCode": "FR",
"geonameId": 3017382
},
"city": {
"geonameId": 2977058,
"name": "Saint-Saulve",
},
"subdivisions": [
{
"name": "Hauts-de-France"
"isoCode": "HDF",
"geonameId": 11071624
},
{
"name": "North",
"isoCode": "59",
"geonameId": 2990129
}
]
}
I would suggest using Moshi (https://github.com/square/moshi/) and a custom adapter (see the examples on the github page) to filter/transform your data, when you read them into your data classes. If you have properly filled data objects, you should be able to write your desired JSON without any problems.

How to get key from ArrayList nested in JSON using Groovy and change its value

I need to be able to find the key quote.orderAttributes[0].attributeDetail.name and set its value to null or any other value I want. I only need to do this for the first element in any list so selecting [0] is fine. I want to be able to use a path such as 'quote.orderAttributes.attributeDetail.name'. But given the amount of time I've spent so far, please advise of any better approaches.
Here is the Json:
{
"source": "source",
"orderId": null,
"Version": null,
"quote": {
"globalTransactionId": "k2o4-6969-1fie-poef",
"quoteStatus": "Not Uploaded",
"events": {
"eventDescription": "event description",
"eventTypeName": "Event Type"
},
"someReport": {
"acceptResultsFlag": "Y",
"orderDate": "2017-06-14",
"orderStatus": "string"
},
"anotherReport": {
"id": 627311,
"orderDate": "2017-06-14"
},
"attributes": [
{
"appliedFlag": "Y",
"attributeDetail": {
"name": "name1",
"value": "value1"
},
"attributeName": "attribute1"
},
{
"appliedFlag": "N",
"attributeDetail": {
"name": "name2",
"value": "value2"
},
"attributeName": "attribute2"
}
],
"orderAttributes": [
{
"appliedFlag": "Y",
"attributeDetail": {
"name": "name3",
"value": "value3"
},
"attributeName": "orderAttribute1"
},
{
"appliedFlag": "N",
"attributeDetail": {
"name": "name4",
"value": "value4"
},
"attributeName": "orderAttribute2"
}
]
}
}
I know the following works but requires that I know which object(s) is an ArrayList and specify its [0] indexed item:
def input = new File("src/test/resources/ShortExample.json")
def json = new JsonSlurper().parse(input)
def option1 = json['quote']["attributes"][0]["attributeDetail"]["name"]
println option1
//or this
//where csvData.fullPath = quote.orderAttributes.attributeDetail.name
def (tkn1, tkn2, tkn3, tkn4) = csvData.fullPath.tokenize('.')
def option2 = json["$tkn1"]["$tkn2"][0]["$tkn3"]["$tkn4"]
println option2
I would like to be able to:
def input = new File("src/test/resources/ShortExample.json")
def json = new JsonSlurper().parse(input)
def changeValueTo = null
def (tkn1, tkn2, tkn3, tkn4) = csvData.fullPath.tokenize('.')
json["$tkn1"]["$tkn2"]["$tkn3"]["$tkn4"] = changeValueTo
I've tried to implement many of the examples on here using recursion, methods creating MapsOrCollections that identify what the object is and then search it for key or value, even trampoline examples.
If you could point me to a good article explaining serialization and deserialization it would be much appreciated too.
Thank you in advance.
as variant:
import groovy.json.*;
def json = '''{
"source": "source",
"orderId": null,
"Version": null,
"quote": {
"globalTransactionId": "k2o4-6969-1fie-poef",
"quoteStatus": "Not Uploaded",
"attributes": [
{
"appliedFlag": "Y",
"attributeDetail": {
"name": "name1",
"value": "value1"
},
"attributeName": "attribute1"
},
{
"appliedFlag": "N",
"attributeDetail": {
"name": "name2",
"value": "value2"
},
"attributeName": "attribute2"
}
]}
}'''
json = new JsonSlurper().parseText(json)
def jsonx(Object json, String expr){
return Eval.me('ROOT',json, expr)
}
println jsonx(json, 'ROOT.quote.attributes[0].attributeDetail.name')
jsonx(json, 'ROOT.quote.attributes[0].attributeDetail.name = null')
println jsonx(json, 'ROOT.quote.attributes[0].attributeDetail.name')
You can access and modify any nested field of JSON object directly, e.g.
json.quote.attributes[0].attributeDetail.name = null
This is possible, because new JsonSlurper().parse(input) returns a groovy.json.internal.LazyMap object. Groovy allows you to access and modify any Map entries using dot notation, e.g.
Map<String, Map<String, Integer>> map = [
lorem: [ipsum: 1, dolor: 2, sit: 3]
]
println map.lorem.ipsum // Prints '1'
map.lorem.ipsum = 10
println map.lorem.ipsum // Prints '10'
You can apply same approach to your example, e.g.
import groovy.json.JsonSlurper
String input = '''{
"source": "source",
"orderId": null,
"Version": null,
"quote": {
"globalTransactionId": "k2o4-6969-1fie-poef",
"quoteStatus": "Not Uploaded",
"events": {
"eventDescription": "event description",
"eventTypeName": "Event Type"
},
"someReport": {
"acceptResultsFlag": "Y",
"orderDate": "2017-06-14",
"orderStatus": "string"
},
"anotherReport": {
"id": 627311,
"orderDate": "2017-06-14"
},
"attributes": [
{
"appliedFlag": "Y",
"attributeDetail": {
"name": "name1",
"value": "value1"
},
"attributeName": "attribute1"
},
{
"appliedFlag": "N",
"attributeDetail": {
"name": "name2",
"value": "value2"
},
"attributeName": "attribute2"
}
],
"orderAttributes": [
{
"appliedFlag": "Y",
"attributeDetail": {
"name": "name3",
"value": "value3"
},
"attributeName": "orderAttribute1"
},
{
"appliedFlag": "N",
"attributeDetail": {
"name": "name4",
"value": "value4"
},
"attributeName": "orderAttribute2"
}
]
}
}'''
def json = new JsonSlurper().parse(input.bytes)
assert json.quote.attributes[0].attributeDetail.name == 'name1'
json.quote.attributes[0].attributeDetail.name = null
assert json.quote.attributes[0].attributeDetail.name == null
I hope it helps.

Table name in a JSON array string

I have a list of two DataTables. I'm converting this list to a JSON array, but I need to add the table name for every DataTable in the JSON string.
How can I do that?
This is how I'm converting the list:
Dim json As String = JsonConvert.SerializeObject(list, New DataTableConverter())
Desired JSON output:
{
"category": [
{
"id": "1",
"desc": "default",
},
{
"id": "2",
"desc": "fun",
}
],
"images": [
{
"image ID": "1",
"link": "images/logo.jpg"
"category": "1"
},
{
"image ID": "2",
"link": "images/logo2.jpg"
"category": "2"
}
]
}
Try putting your tables into a DataSet instead of a list, then serialize the DataSet.
Dim table1 As New DataTable("category")
table1.Columns.Add("id", GetType(String))
table1.Columns.Add("desc", GetType(String))
table1.Rows.Add("1", "default")
table1.Rows.Add("2", "fun")
Dim table2 As New DataTable("images")
table2.Columns.Add("image ID", GetType(String))
table2.Columns.Add("link", GetType(String))
table2.Columns.Add("category", GetType(String))
table2.Rows.Add("1", "images/logo.jpg", "1")
table2.Rows.Add("2", "images/logo2.jpg", "2")
Dim dataSet As New DataSet()
dataSet.Tables.Add(table1)
dataSet.Tables.Add(table2)
Dim json As String = JsonConvert.SerializeObject(dataSet, Formatting.Indented)
Console.WriteLine(json)
Output:
{
"category": [
{
"id": "1",
"desc": "default"
},
{
"id": "2",
"desc": "fun"
}
],
"images": [
{
"image ID": "1",
"link": "images/logo.jpg",
"category": "1"
},
{
"image ID": "2",
"link": "images/logo2.jpg",
"category": "2"
}
]
}

parse nested json to backbone collections

I'm just starting with Backbone and I'm running into a problem. I have a nice restful setup. For most of my GET request I receive a single collection of models, but for one I am loading nested relational data, which creates nested JSON.
In Backbone I have the following Models:
App.Models.Sequence = Backbone.Model.extend({});
App.Models.Layer = Backbone.Model.extend({});
App.Models.Item = Backbone.Model.extend({});
and these collections
App.Collections.Sequences = Backbone.Collection.extend({
model: App.Models.Sequence,
url: '/api/sequences/'
});
App.Collections.Layers = Backbone.Collection.extend({
model: App.Models.Layer,
url: '/api/layers'
});
App.Collections.Items = Backbone.Collection.extend({
model: App.Models.Item,
url: '/api/items'
});
I load data as JSON:
[
{
"id": "1",
"project_id": "8",
"name": "Seq1",
"layers": [
{
"id": "1",
"name": "Layer11",
"sequence_id": "1",
"items": [
{
"id": "1000000",
"layer_id": "1",
"itemtype_id": "1",
"position": "0"
},
{
"id": "1000001",
"layer_id": "1",
"itemtype_id": "2",
"position": "0"
},
{
"id": "1000002",
"layer_id": "1",
"itemtype_id": "2",
"position": "0"
},
{
"id": "1000003",
"layer_id": "1",
"itemtype_id": "4",
"position": "0"
}
]
},
{
"id": "2",
"name": "Layer12",
"sequence_id": "1",
"items": [
{
"id": "1000004",
"layer_id": "2",
"itemtype_id": "1",
"position": "0"
},
{
"id": "1000005",
"layer_id": "2",
"itemtype_id": "2",
"position": "0"
},
{
"id": "1000006",
"layer_id": "2",
"itemtype_id": "3",
"position": "0"
},
{
"id": "1000007",
"layer_id": "2",
"itemtype_id": "4",
"position": "0"
}
]
},
{
"id": "3",
"name": "Layer13",
"sequence_id": "1",
"items": [
{
"id": "1000008",
"layer_id": "3",
"itemtype_id": "1",
"position": "0"
},
{
"id": "1000009",
"layer_id": "3",
"itemtype_id": "4",
"position": "0"
},
{
"id": "1000010",
"layer_id": "3",
"itemtype_id": "5",
"position": "0"
}
]
}
]
},
{
"id": "2",
"project_id": "8",
"name": "Seq2",
"layers": [
{
"id": "4",
"name": "Layer21",
"sequence_id": "2",
"items": []
},
{
"id": "5",
"name": "Layer22",
"sequence_id": "2",
"items": []
}
]
},
{
"id": "3",
"project_id": "8",
"name": "Seq3",
"layers": [
{
"id": "6",
"name": "Layer31",
"sequence_id": "3",
"items": []
},
{
"id": "7",
"name": "Layer32",
"sequence_id": "3",
"items": []
}
]
}
]
How can I get Sequences, Layers and Items into my collections?
You can use a combination of underscore's flatten and pluck to do this neatly:
var data = { /* your JSON data */ };
var allSequences = _.clone(data);
var allLayers = _.flatten(_.pluck(allSequences, 'layers'));
var allItems = _.flatten(_.pluck(allLayers, 'items'));
var sequences = new App.Collections.Sequences(allSequences);
var layers = new App.Collections.Layers(allLayers);
var items = new App.Collections.Items(allItems);
If you don't want Sequences and Layers to contain their child objects, override Model.parse to trim them. For example:
App.Models.Sequence = Backbone.Model.extend({
parse: function(attrs) {
delete attrs.layers;
return attrs;
}
});
And initialize/add the collection with the parse:true option:
var sequences = new App.Collections.Sequences(allSequences, {parse:true});
Et cetera.