How to make com.fasterxml.jackson print array vertically? [duplicate] - java

I have data that looks like this:
{
"status": "success",
"data": {
"irrelevant": {
"serialNumber": "XYZ",
"version": "4.6"
},
"data": {
"lib": {
"files": [
"data1",
"data2",
"data3",
"data4"
],
"another file": [
"file.jar",
"lib.jar"
],
"dirs": []
},
"jvm": {
"maxHeap": 10,
"maxPermSize": "12"
},
"serverId": "134",
"version": "2.3"
}
}
}
Here is the function I'm using to prettify the JSON data:
public static String stringify(Object o, int space) {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(o);
} catch (Exception e) {
return null;
}
}
I am using the Jackson JSON Processor to format JSON data into a String.
For some reason the JSON format is not in the format that I need. When passing the data to that function, the format I'm getting is this:
{
"status": "success",
"data": {
"irrelevant": {
"serialNumber": "XYZ",
"version": "4.6"
},
"another data": {
"lib": {
"files": [ "data1", "data2", "data3", "data4" ],
"another file": [ "file.jar", "lib.jar" ],
"dirs": []
},
"jvm": {
"maxHeap": 10,
"maxPermSize": "12"
},
"serverId": "134",
"version": "2.3"
}
}
}
As you can see under the "another data" object, the arrays are displayed as one whole line instead of a new line for each item in the array. I'm not sure how to modify my stringify function for it to format the JSON data correctly.

You should check how DefaultPrettyPrinter looks like. Really interesting in this class is the _arrayIndenter property. The default value for this property is FixedSpaceIndenter class. You should change it with Lf2SpacesIndenter class.
Your method should looks like this:
public static String stringify(Object o) {
try {
ObjectMapper mapper = new ObjectMapper();
DefaultPrettyPrinter printer = new DefaultPrettyPrinter();
printer.indentArraysWith(new Lf2SpacesIndenter());
return mapper.writer(printer).writeValueAsString(o);
} catch (Exception e) {
return null;
}
}

I don't have enough reputation to add the comment, but referring to the above answer Lf2SpacesIndenter is removed from the newer Jackson's API (2.7 and up), so instead use:
printer.indentArraysWith(DefaultIndenter.SYSTEM_LINEFEED_INSTANCE);
Source of the solution

Related

How to update Rest API request Body array

I am trying to automate one API using rest API JAVA. I have kept sample request json in one file and before passing that json I want to modify some values. New values are in Map.
For example I want to modify 'company' value to 'Microsoft'(which is in hashmap newInputs). Problem is my code is adding new 'company' at the top of body instead of updating it. How do i update specific values in Items array.
json body in file
{
"Items": [
{
"newValue": "Q3",
"company": "Test",
"oldValue": "Q2",
"Date": "2022-03-27"
}
]
}
What i want to pass to API
{
"Items": [
{
"newValue": "Q3",
"company": "Microsoft",
"oldValue": "Q2",
"Date": "2022-03-27"
}
]
}
What my code is passing
{
"company": "Microsoft",
"Items": [
{
"newValue": "Q3",
"company": "Test",
"oldValue": "Q2",
"Date": "2022-03-27"
}
]
}
My code
public static String createItem(Map<String, String> newInputs) {
JSONArray jsonArray = null;
JSONObject jsonObject;
try {
jsonArray = new JSONArray(new String(
Files.readAllBytes(Paths.get("src", "test", "resources", "Payloads", "testdata.json"))));
jsonObject = new JSONObject(jsonArray.get(0).toString());
for (String key : newInputs.keySet()) {
jsonObject.put(key, newInputs.get(key));
}
jsonArray.put(0, jsonObject);
}

How to write custom json serializer and serialize value as an array

I need to serialize simple java object with three fields (one is a List of objects) into json to look something like this:
{
"id": "1",
"fields": [
{
"value": {
"someNumber": "0.0.2"
},
"id": "67"
}
],
"name": "Daniel"}
I've read guides on custom serializers StdSerializer and JsonGenerator, as i undestood, to write "name": "Daniel" into json you need to do somwthing like gen.writeObjectField("name", name); but i cannot get my head on two things:
How to write some string value like here:
"value": {
"name": "0.0.2"
},
And how to write java List as an array like this:
"fields": [
{
"value": {
"someNumber": "0.0.2"
},
"id": "67"
}]
where "fields" is an List full of objects having two fields: "value" and "id".
Any help is appreciated
like this
public class Test {
public static void main(String[] args) throws IOException {
String ret;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectMapper mapper = new ObjectMapper();
JsonGenerator jg = mapper.getJsonFactory().createJsonGenerator(new PrintWriter(bos));
jg.writeStartObject();
jg.writeStringField("id", "1");
jg.writeArrayFieldStart("fields");
jg.writeStartObject();
jg.writeObjectFieldStart("value");
jg.writeStringField("someNumber","0.0.2");
jg.writeEndObject();
jg.writeStringField("id","67");
jg.writeEndObject();
//you can write more objects in fields here
jg.writeEndArray();
jg.writeStringField("name","Daniel");
jg.writeEndObject();
jg.flush();
jg.close();
ret = bos.toString();
bos.close();
System.out.println(ret);
}
}
and the result is
{
"id":"1",
"fields":[
{
"value":{
"someNumber":"0.0.2"
},
"id":"67"
}
],
"name":"Daniel"
}

Mapping JSON with nested object to GSON

I have a JSON schema class that is auto generate using AVRO. I would like to create a GSON object using this JSON. I try to do so using this code
#Test
public void parseJson() {
JSONParser jsonParser = new JSONParser();
try {
JSONObject jsonObject = (JSONObject) jsonParser.parse(new FileReader("/pathto/test.json"));
ThinEvent thinEvent = new Gson().fromJson(jsonObject.toString(), ThinEvent.class);
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
}
but this results in the following error ... It looks like GSON is looking for a string but the json actually contains a nested object? The ThinEvent object has refService declared as a list.
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 74 path $.references[0].refService
private java.util.List<com.lm.gde.eventing.avro.Reference> references;
Here is my JSON, I have replaced some values with XXXX.
{
"eventType": "policy.PolicyPremiumChangedEvent",
"correlationId": "XXXX",
"references": [
{
"ref": "XXX",
"refType": "policy_id",
"refService": {
"com.lm.gde.eventing.avro.RefService": "policy_service"
},
"links": {
"array": [
{
"refUri": ""
}
]
}
},
{
"ref": "XXXXXX",
"refType": "policy_number",
"refService": {
"com.lm.gde.eventing.avro.RefService": "policy_service"
},
"links": {
"array": [
{
"refUri": "XXXXXX"
}
]
}
},
{
"ref": "2019-09-28",
"refType": "policy_tx_effective_date",
"refService": {
"com.lm.gde.eventing.avro.RefService": "policy_service"
},
"links": {
"array": [
{
"refUri": "XXXXX"
}
]
}
}
],
"eventContext": null,
"Timestamp": 1569574003295,
"Version": "1"
}
GSON supports nested objects check this article. Just create model that matches the Json (but in Java/Kotlin) and toss it to GSON. Same with collections. You can even use List instead of arrays.
You could just get the json file as a complete string and deserialize that as well.

JSONObject is not getting converted to String properly

I am converting JSONObject to String. I am using below code:
String decresponse=obj.getFileWithUtil("Files/v3user22.txt");
System.out.println("Decrypted string is "+decresponse);
JSONObject js = JSONObject(decresponse);
System.out.println("JSON Object is "+js.toString());
Here, i am getting the value of decresponse from a file since the json is very large. Value of decresponse is:
{
"userid":123456,
"status":"SUCCESS",
"name":{
"firstName":"firstname",
"lastName":"lastname"
},
"dob":"03/02/1993",
"gender":"M",
"kycType":"Manual",
"address":{
"permanentAddress":{
"country":"INDIA",
"street_1":"K-26",
"street_2":"",
"city":"North",
"state":"Delhi",
"postal_code":"110052",
"locality":"abc"
},
"correspondenceAddress":{
"country":"INDIA",
"street_1":"abc",
"street_2":"abc",
"city":"ABC",
"state":"Punjab",
"postal_code":"111000",
"locality":"def"
}
},
"docs":[
{
"nameOnDoc":"name",
"verificationStatus":"FAILED",
"kycNameMatch":"SUCCESS",
"docCode":"aadhar",
"docValue":"1898989",
"submittedAs":"AdditionalDoc"
},
{
"nameOnDoc":"abc",
"verificationStatus":"NOT_ATTEMPTED",
"kycNameMatch":"NOT_ATTEMPTED",
"docCode":"pan",
"docValue":"KSKA1234F",
"submittedAs":"AdditionalDoc",
"expiryDate":"03/02/2018"
},
{
"docCode":"voter",
"docValue":"CIBPS2107P",
"submittedAs":"Poi_Poa"
}
],
"agents":[
{
"bankAgentType":"BF",
"agentBranch":"nodia",
"agentDesignation":"agent manager",
"agentEmpcode":"1010111",
"custId":"119990",
"agentId":"",
"agencyType":"CFA",
"agencyName":"internal"
},
{
"bankAgentType":"BC",
"agentBranch":"nodia",
"agentDesignation":"agent manager",
"agentEmpcode":"",
"custId":"119999",
"agentId":"MORPHO-1782",
"agencyType":"VA",
"agencyName":"morpho"
}
],
"relatives":[
{
"relationShip":"FATHER",
"firstName":"firstname",
"lastName":"lastname"
},
{
"relationShip":"MOTHER",
"firstName":"firstname",
"lastName":"lastname"
}
],
"useKycDetails":"UNDER_REVIEW",
"amlflags":{
"sanction":"N",
"pep":"N"
},
"walletflags":{
"upgraded":"1",
"updated":"1",
"blocked":"0"
},
"suspended":"false",
"aadhar_type1_check":"FAILED",
"aadhar_kyc_name_check":"SUCCESS",
"aadharSubmittedAs":"AdditionalDoc",
"aadharVerified":"false",
"panSubmittedAs":"AdditionalDoc",
"panVerified":"false",
"maritalStatus":"MARRIED",
"profession":"PRIVATE_SECTOR_JOB",
"nationality":"INDIAN",
"kycVerificationDate":"04/01/2017",
"declarationPlace":"Delhi",
"dmsInfos":[
{
"type":"",
"dmsid":""
}
],
"aadharAuthCode":"56bd65db0dbc4b2a848841a44eabb54e",
"agriculturalIncome":"100000",
"nonAgriculturalIncome":"50000",
"seedingStatus":"consent_given"
}
But, on converting the json object to string the value comes as below:
{
"panVerified":"false",
"gender":"M",
"userid":123456,
"panSubmittedAs":"AdditionalDoc",
"aadharAuthCode":"56bd65db0dbc4b2a848841a44eabb54e",
"docs":[
{
"kycNameMatch":"SUCCESS",
"verificationStatus":"FAILED",
"nameOnDoc":"name",
"docCode":"aadhar",
"docValue":"1898989",
"submittedAs":"AdditionalDoc"
},
{
"expiryDate":"03/02/2018",
"kycNameMatch":"NOT_ATTEMPTED",
"verificationStatus":"NOT_ATTEMPTED",
"nameOnDoc":"abc",
"docCode":"pan",
"docValue":"KSKA1234F",
"submittedAs":"AdditionalDoc"
},
{
"docCode":"voter",
"docValue":"CIBPS2107P",
"submittedAs":"Poi_Poa"
}
],
"aadhar_type1_check":"FAILED",
"aadharSubmittedAs":"AdditionalDoc",
"useKycDetails":"UNDER_REVIEW",
"kycVerificationDate":"04/01/2017",
"kycType":"Manual",
"profession":"PRIVATE_SECTOR_JOB",
"address":{
"permanentAddress":{
"country":"INDIA",
"street_1":"K-26",
"city":"North",
"street_2":"",
"locality":"abc",
"state":"Delhi",
"postal_code":"110052"
},
"correspondenceAddress":{
"country":"INDIA",
"street_1":"abc",
"city":"ABC",
"street_2":"abc",
"locality":"def",
"state":"Punjab",
"postal_code":"111000"
}
},
"nonAgriculturalIncome":"50000",
"seedingStatus":"consent_given",
"dmsInfos":[
{
"dmsid":"",
"type":""
}
],
"relatives":[
{
"firstName":"firstname",
"lastName":"lastname",
"relationShip":"FATHER"
},
{
"firstName":"firstname",
"lastName":"lastname",
"relationShip":"MOTHER"
}
],
"suspended":"false",
"agents":[
{
"agentId":"",
"agentEmpcode":"1010111",
"custId":"119990",
"agentBranch":"nodia",
"agentDesignation":"agent manager",
"bankAgentType":"BF",
"agencyType":"CFA",
"agencyName":"internal"
},
{
"agentId":"MORPHO-1782",
"agentEmpcode":"",
"custId":"119999",
"agentBranch":"nodia",
"agentDesignation":"agent manager",
"bankAgentType":"BC",
"agencyType":"VA",
"agencyName":"morpho"
}
],
"amlflags":{
"sanction":"N",
"pep":"N"
},
"aadhar_kyc_name_check":"SUCCESS",
"nationality":"INDIAN",
"dob":"03/02/1993",
"walletflags":{
"upgraded":"1",
"blocked":"0",
"updated":"1"
},
"name":{
"firstName":"firstname",
"lastName":"lastname"
},
"aadharVerified":"false",
"maritalStatus":"MARRIED",
"status":"SUCCESS",
"declarationPlace":"Delhi",
"agriculturalIncome":"100000"
}
Why am I getting different values?
Why am I getting different values
Those values are not that different. They simply have key:value pairs in different order.
JSON structure holds key:value pairs where keys are unique. In most cases order of keys is not important so classes like org.json.JSONObject are storing them in internal HashMap which doesn't preserve insertion order (but allows quick access to values).
When toString() is invoked internally it builds String using that HashMap iterator, so order depends on amount of keys and their hashes, not insertion order.
If you want to preserve order consider using other libraries like gson. Your parsing could look like:
JsonParser jsonParser = new JsonParser();
JsonObject js = jsonParser.parse(decresponse).getAsJsonObject();
and js.toString() would result in
{"userid":123456,"status":"SUCCESS","name":{"firstName":"firstname", ... which seems to be what you ware after.

Gson help with parse array - works without array but won't with array

Can somebody help me with Gson parser. When I remove change from JSON and Result it works fine but with change it throws JsonParseException-Parse failed.
Result[] response = gson.fromJson(fileData.toString(), Result[].class);
I have classes like this
public class Result {
public String start_time;
public String end_time;
public change[] change;
}
and
public class change {
public String id;
public String name;
}
and Json string like
[
{
"start_time": "8:00",
"end_time": "10:00",
"change": [
{
"id": "1",
"name": "Sam"
},
{
"id": "2",
"name": "John"
}
]
},
{
"start_time": "9:00",
"end_time": "15:00",
"change": [
{
"id": "1",
"name": "Sam"
},
{
"id": "2",
"name": "John"
}
]
}
]
Can somebody tell me what I did wrong ? Any idea why it won't work with array ?
As has been suggested, you need to use a list instead. Gson has pretty good documentation for using parametized types with the parser, you can read more about it here. Your code will end up looking like this:
Type listType = new TypeToken<List<Result>>() {}.getType();
List<Result> results = gson.fromJson(reader, listType);
for (Result r : results) {
System.out.println(r);
}

Categories