This question already has answers here:
Convert JSON to YAML. Parsing JSON to YAML
(7 answers)
Closed 2 years ago.
I want to convert JSON to YAML. And I want to this in Java dynamically. Based on the componentId, properties will change. This JSON can vary and supports multiple componentIds and this comes from HTTP request.
Example JSON:
[
{
"id": "timer",
"attributes": {
"type": "tick"
"period": "5000"
},
"output": "transform"
},
{
"id": "transform",
"attributes": {
"expression": "${body.toUpperCase()}”,
“type”: “simple"
},
"output": "log"
},
{
"id": "log",
"attributes": {
"message": "hello world”,
“type”: “info"
}
}
]
Expected YAML:
- from:
uri: "timer:tick"
parameters:
period: "5000"
steps:
- set-body:
constant: "Hello Yaml!!!"
- transform:
simple: "${body.toUpperCase()}"
- to: "log:info”
I think you should be able to convert any kind of JSON to YAML using Jackson. Add the following dependencies to your project:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<version>${jackson.version}</version>
</dependency>
If you have an input Kamelet JSON string like this:
{
"apiVersion": "camel.apache.org/v1alpha1",
"kind": "Kamelet",
"metadata": {
"name": "echo-sink",
"labels": {
"camel.apache.org/kamelet.type": "sink"
}
},
"spec": {
"definition": {
"title": "Echo",
"description": "Replies with an echo message to each incoming event",
"properties": {
"prefix": {
"title": "Prefix",
"description": "The prefix to prepend to the incoming event",
"type": "string",
"default": "echo: "
}
}
},
"types": {
"in": {
"mediaType": "text/plain"
},
"out": {
"mediaType": "text/plain"
}
},
"flow": {
"from": {
"uri": "kamelet:source",
"steps": [
{
"set-body": {
"simple": "{{prefix}}${body}"
}
}
]
}
}
}
}
You can easily convert it into YAML using Jackson like this:
File jsonFile = new File(JsonToYaml.class.getResource("/kamelet.json").getFile());
ObjectMapper jsonMapper = new ObjectMapper();
YAMLMapper yamlMapper = new YAMLMapper();
// Read file as JsonNode
JsonNode jsonNode = jsonMapper.readTree(jsonFile);
// Convert it into YAML String
String yamlOutput = yamlMapper.writeValueAsString(jsonNode);
System.out.println(yamlOutput);
Related
I'm having difficulty implementing a JSON to send as a POST call in Spring.
Which is the fastest and most effective way to turn this json into a java object or a map and make the call?
below is an example of a json to send:
{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"name": "edge-ws"
},
"spec": {
"selector": {
"matchLabels": {
"run": "edge-ws"
}
},
"replicas": 1,
"template": {
"metadata": {
"labels": {
"run": "edge-ws"
}
},
"spec": {
"containers": [
{
"name": "edge-ws",
"image": "server-tim:latest",
"imagePullPolicy": "Never",
"ports": [
{
"containerPort": 80
}
]
}
]
}
}
}
}
this and the second body that has a value (nodeport) that must be taken from a field entered by the user front end side.(page created in html)
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "edge-ws",
"labels": {
"run": "edge-ws"
}
},
"spec": {
"type": "NodePort",
"ports": [
{
"port": 8080,
"targetPort": 80,
"nodePort": 30200,
"protocol": "TCP",
"name": "http"
}
],
"selector": {
"run": "edge-ws"
}
}
}
Both files must be sent with a single click on a button on the front end side.the first call with the first body starts and if everything is ok the second body starts
What should the class that maps objects look like? What should the controller look like instead?
They also gave me an address to call that can only be used on the machine, how can I test this call locally?
Thanks in advance!
You can use google's Gson library to convert the JsonString to Object and then use below code:
Gson gson = new Gson();
Object requestObject = gson.fromJson(jsonString, Object.class);
ResponseObject responseObject = restTemplate.postForObject(url, requestObject, ResponseObject.class);
I'm Using RestAssured,
and i'm getting the response like this-
{
"Data": {
"Sub": {
"SubDetails": [
{
"OrgId": 5,
"SubId": 1,
"SubName": "Mathematics"
}
]
}
},
"RawData": {
"Url": "http://localhost:11111/cases/case-15",
"Type": "Rest",
"Request": {
"Details": {
"OrganizationId": 5,
"Student": {
"Age": 30,
"Religion": "Hindu",
"StudentId": 10
}
}
},
"Response": {
"SmartReturnObject": {
"Subject": [
{
"SubjectId": 1,
"SubjectName": "Mathematics"
}
],
"OrganizationId": 5
}
},
"IsApiError": false
},
"SessionId": "5q0",
"RequestUniqueId": "4543534",
"StatusCode": "4540000",
"StatusMessage": "Success",
"DataSource": "DD"
}
Now i need to extract the Data object separate and RawData separate but i'm failed.
I tried with JSONPath also but not getting it in JSON format.
I tried
JsonPath body= response.jsonPath();
Object value=body.get("Data");
System.out.println("Value is-"+value);
and getting it like this - {Sub={SubDetails=[{OrgId=5, SubId=1, SubName=Mathematics}]}}
I want the response as instanceof JSONObject or JSONArray type.
pom.xml
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
Try below -
Gson gson = new Gson();
try {
JSONObject obj = new JSONObject(gson.toJson(givenString));
}catch (Exception e){
System.out.println(e.toString());
}
I have a JSON file like this:
{
"Resources": {
"HelloWorldFunction": {
"Type": "AWS::Serverless::Function",
"Properties": {
"Handler": "index.handler",
"Runtime": "nodejs8.10",
"Events": {
"HelloWorldApi": {
"Type": "Api",
"Properties": {
"Path": "/",
"Method": "GET"
}
}
},
"Policies": [
{
"SNSPublishMessagePolicy": {
"TopicName": {
"Fn::GetAtt": [
"HelloWorldTopic",
"TopicName"
]
}
}
}
],
"Environment": {
"Variables": {
"SNS_TOPIC_ARN": {
"Ref": "HelloWorldTopic"
}
}
},
"CodeUri": "nothing"
}
},
"HelloWorldTopic": {
"Type": "AWS::SNS::Topic",
"Properties": {
"Subscription": [
{
"Endpoint": "nothing",
"Protocol": "email"
}
]
}
}
}
}
I am using the Jackson YAMLFactory to parse a YAML-file that is equivalent to this JSON. How can I parse this in a way that all the content inside "Resources" is stored in a single String? (I want to keep this as a separate YAML/JSON for further analysis)
ObjectMapper mapper = new ObjectMapper();
String resources = mapper.readTree(new FileReader(path_to_your_json_file).at("/Resources").asText()
Or something like this.
{
"icon": "service",
"title": "A",
"type": "service",
"children": [
{
"icon": "sharedlibraries",
"title": "sharedlibraries",
"type": "sharedlibraries",
"children": [
{
"icon": "war",
"title": "abc.war ( ui-shared-lib )",
"path": "abc/common/Services/1.2.0/lib/comp.war",
"reference": >"abc/common/templates/applications/11.1.2.3.jar/config/config.xml",
"type": "sharedlibrary",
"version": "11.1.2.0#11.1.2.0",
"children": [
{
"icon": "jar",
"title": "comp1.jar",
"path": >"abc/common/SharedServices/1.2.0/lib/comp.war/WEB-INF/lib/comp.jar",
"reference": >"abc/common/Services/1.2.0/lib/comp.war/WEB-INF/lib",
"type": "jar",
"thirdpartyjar": "true"
}
]
},
:
:
:
}
I would need to retrieve, attribute "path", of all nodes with name "children", whose "thirdpartyjar" atribute= true. Is this possible using jackson?
Update: I tried following:
public void parse(File file) throws JsonProcessingException,
IOException {
ObjectMapper objectMapper = new ObjectMapper();
//JsonNode rootNode = objectMapper.readTree(file);
Model model = objectMapper.readValue(file, Model.class);
listThirdPartyJars(model);
while (true) {
Model children = model.getChildren();
if (!(children == null)) {
listThirdPartyJars(children);
model = children;
} else {
break;
}
}
}
public void listThirdPartyJars(Model model) {
boolean thirdPartyJars = model.isThirdPartyJar();
if (thirdPartyJars == true)
System.out.println(model.getPath());
}
But, came across following exception:
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of com.manager.Model out of START_ARRAY token
at [Source: D:\my_json.json; line: 4, column: 22] (through reference chain: com.manager.Model["children"])
Considering the JSON you posted in your question (with a few fixes to make it valid):
{
"icon": "service",
"title": "A",
"type": "service",
"children": [
{
"icon": "sharedlibraries",
"title": "sharedlibraries",
"type": "sharedlibraries",
"children": [
{
"icon": "war",
"title": "abc.war ( ui-shared-lib )",
"path": "abc/common/Services/1.2.0/lib/comp.war",
"reference": "abc/common/templates/applications/11.1.2.3.jar/config/config.xml",
"type": "sharedlibrary",
"version": "11.1.2.0#11.1.2.0",
"children": [
{
"icon": "jar",
"title": "comp1.jar",
"path": "abc/common/SharedServices/1.2.0/lib/comp.war/WEB-INF/lib/comp.jar",
"reference": "abc/common/Services/1.2.0/lib/comp.war/WEB-INF/lib",
"type": "jar",
"thirdpartyjar": "true"
}
]
}
]
}
]
}
Using Jayway JsonPath and a query such as $..children[?(#.thirdpartyjar=='true')].path will do the trick and will give you the following result:
[
"abc/common/SharedServices/1.2.0/lib/comp.war/WEB-INF/lib/comp.jar"
]
You can test it here.
Using Jayway JsonPath
To use Jayway JsonPath, add the following dependency to your project:
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.3.0</version>
</dependency>
And then read the JSON document:
String json = "...";
List<String> paths = JsonPath.read(json, "$..children[?(#.thirdpartyjar=='true')].path");
Alternatively to Jayway JsonPath, you can map your JSON to Java classes (or simply use the Jackson Tree Model), parse the JSON using Jackson, iterate recursively over the tree and extract the data you need.
Yes, it's possible. You would need to have a model which references itself as an attribute, somewhat like :
public class Model {
String icon;
String title;
String path;
String reference;
String type;
String version;
boolean thirdPartyJar;
Model children;
...getters, setters and overriden methods
}
And you can map your Json string to this object using ObjectMapper to further access the children with attribute thirdPartyJar as true.
I have a json such as below
{
"apiVersion": "v1",
"metadata": {
"status": {
"statusCode": 0
},
},
"stuff": [
{
"name": {
"text": "red"
},
"properties": [
{
"attributes": {
"shade": "dark"
},
"component": {
"id": "BA1",
}
"type": "Color"
}
]
},
{
"name": {
"text": "Toyota Camry"
},
"properties": [
{
"attributes": {},
"component": {
"id": "MS",
},
"type": "Vehicle"
}
]
},
]
}
I'm using GSON to parse the results like this:
Gson gson = new Gson();
JsonObject json = (JsonObject) gson.fromJson(in, JsonObject.class);
System.out.println(json.get("apiVersion").getAsString());
I can get the apiVersion but don't know how to get elements that are inside the json tree. For example, type...what if I want to output all the different type..in this case Color and Vehicle
I must be missing something here, but why can't you nest calls to getJsonObject? For example, to get the status code:
System.out.println(json.getAsJsonObject("metadata")
.getAsJsonObject("status")
.get("statusCode").getAsInt());
You can create an object in that matter and to parse the json to it (with GSON):
ParsedObject parsedObject = new Gson().fromJson(json, ParsedObject.class);
public class ParsedObject {
#SerializedName(value = "apiVersion")
private String mApiVersion;
#SerializedName(value = "metadata")
private Metadata mMetadata;
}