GSON - Creating JSON string from Object and viseversa - json

I've a simple object like this
public class WebMessage
{
public String destinationAddress;
public String clientType;
public JsonObject params;
}
When i want to create a JSON string from this object using GSON i do it like the following:
WebMessage parringMsg = new WebMessage();
JsonObject parameters = new JsonObject();
parameters.addProperty("action", "PARRING_START");
parringMsg.params = parameters;
String finalString = jsonString.toJson(parringMsg);
But final string looks like this:
{"params":{"members":{"action":"PARRING_START"}}}
I dont understand why my action key is placed inside a members key. Why is that?
I want it to look like this:
{"params":{"action":"PARRING_START"}}

Instead of using a JSONObject inside my Class i used a HashMap like so:
public class WebMessage
{
public WebMessage()
{
params = new HashMap<>();
}
public String destinationAddress;
public String clientType;
public HashMap<String,String> params;
}
Then i could simply put values in there like this, which is also much simpler:
WebMessage parringMsg = new WebMessage();
parringMsg.params.put("action", "PARRING_START");
String finalString = jsonString.toJson(parringMsg);
With the above i get the desired output in finalString:
{"params":{"action":"PARRING_START"}}

Related

Add Argument to existing Json String

I have this situation:
More servlets set the httpservletResponse content-type to json/application.
I output my json this way:
out.write (new Gson().toJson(myObject));
where myObject, is an object and the code above provides creating a string json like using myObject structure.
Now I need to add an argument on the top of the json, because I need an argument like: "result":"okay".
Is there a way to add this without changinc myObject class?
Thanks in advance.
Yes. Instead of building a String using Gson#toJson() use Gson#toJsonTree() which parses the object but creates a JSON internal representation using JsonElement subclasses. You will need to cast it to a JsonObject, then add the new property and finally write it to the output stream.
Code example:
package net.sargue.gson;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
public class SO36837061 {
public static class MyClass {
int a = 1;
String b = "salut";
}
public static void main(String[] args) {
MyClass myObject = new MyClass();
JsonObject jsonObject = (JsonObject) new Gson().toJsonTree(myObject);
jsonObject.addProperty("result", "okay");
String json = new Gson().toJson(jsonObject);
System.out.println("json = " + json);
}
}
Output:
json = {"a":1,"b":"salut","result":"okay"}

How to parse json string in apex

i have json string like this downbelow
{"0":{"in":"mmm","loc":"1234"},"1":{"in":"mmm","loc":"1234"}}
Now i need to parse them as like
in | loc
---------
mmm| 1234
mmm| 1234
So far i did
public with sharing class Search
{
public String strTag {get;set;}
public String strlocation {get;set;}
public String result {get;set;}
public PageReference find() {
HttpRequest req = new HttpRequest();
HttpResponse res = new HttpResponse();
Http http = new Http();
req.setEndpoint('http://test.3spire.net/index.php?in='+strTag+'&loc='+strlocation);
req.setMethod('GET');
//these parts of the POST you may want to customize
req.setCompressed(false);
req.setBody('key1=value1&key2=value2');
req.setHeader('Content-Type', 'application/x-www-form-urlencoded');
try {
res = http.send(req);
} catch(System.CalloutException e) {
system.debug('Callout error: '+ e);
result = ''+e;
}
Result results = (Result) JSON.deserialize(res.getBody(),ResultSet.class);
result = res.getBody();
system.debug(res.getBody());
return null;
}
public class ResultSet{
public List<Result> resultSet;
}
public class Result
{
public String ins;
public String loc;
}
}
But its returns
System.TypeException: Invalid conversion from runtime type Search.ResultSet to Search.Result
How can i solved this problem
Thanks in advance
You are calling JSON.deserialize(res.getBody(),ResultSet.class). The second parameter ResultSet is the Apex object type you want the result to be. But then you attempt to cast it to a type of Result instead.
Either do
Result results = JSON.deserialize(res.getBody(), Result.class);
or
ResultSet results = JSON.deserialize(res.getBody(), ResultSet.class);
In your case, based on the JSON it would seem you want the second option. However, your JSON doesn't quite match your ResultSet class either. Your JSON is a map, not a list. Also, there's a field mismatch between "in" and "ins". This JSON is what would match your ResultSet class:
{{"ins":"mmm","loc":"1234"},{"ins":"mmm","loc":"1234"}}

Json file generation using Javascript serializer

I need to generate the following json files using Javascript serializer,
1. {"components":[{"name":"AA"}]}
2. {"customfield_10222":[{"name":"xxx"},{"name":"yyyy"}]} // this custom field represents the additional notification persons.
I have to achieve this scenario using the below coding,
public List<AdditionalUsers> AdditionalNotification = new List<AdditionalUsers>();
public List<ComponentsDetails> Component = new List<ComponentsDetails>();
class AdditionalUsers
{
public string name;
}
class ComponentsDetails
{
public string name;
}
string[] a=new string[2]{"XXX","YYY"};
foreach (string additionalUser in a)
{
AdditionalNotification.Add(new AdditionalUsers() { name =additionalUser });
}
Component.Add(new ComponentsDetails() { name = "AA" });
var subFields = new Dictionary<string, object>();
subFields.Add("components", Component); // represents 1 json file
subFields.Add("customfield_10222", AdditionalNotification); // represents 2 json file
JavaScriptSerializer serializer = new JavaScriptSerializer();
string json = serializer.Serialize((Object)subFields);
Console.WriteLine(json);
The result like this
{
"components":[{"name": "AA"}],
"customfield_10222":[{"name":"XXX"},{"name":"YYY"}]
}

How to serialize Json string in apex

I need to parse this json string to values.
"start": { "dateTime": "2013-02-02T15:00:00+05:30" }, "end": { "dateTime": "2013-02-02T16:00:00+05:30" },
The problem is I am using JSONParser in apex (salesforce).
And my class is:
public class wrapGoogleData{
public string summary{get;set;}
public string id{get;set;}
public string status;
public creator creator;
public start start;
public wrapGoogleData(string entnm,string ezid,string sta, creator c,start s){
summary= entnm;
id= ezid;
status = sta;
creator = c;
start = s;
}
}
public class creator{
public string email;
public string displayName;
public string self;
}
public class start{
public string datetimew;
}
I am able to get all the datat from this except the datetime in the above string. As datetime is a reserved keyword in apex so i am not able to give the variable name as datetime in my class.
Any suggestion !!
Json Parser code:
JSONParser parser = JSON.createParser(jsonData );
while (parser.nextToken() != null) {
// Start at the array of invoices.
if (parser.getCurrentToken() == JSONToken.START_ARRAY) {
while (parser.nextToken() != null) {
// Advance to the start object marker to
// find next invoice statement object.
if (parser.getCurrentToken() == JSONToken.START_OBJECT) {
// Read entire invoice object, including its array of line items.
wrapGoogleData inv = (wrapGoogleData)parser.readValueAs(wrapGoogleData.class);
String s = JSON.serialize(inv);
system.debug('Serialized invoice: ' + s);
// Skip the child start array and start object markers.
//parser.skipChildren();
lstwrap.put(inv.id,inv);
}
}
}
}
Similar to Kumar's answer but without using an external app.
Changing your start class was the right idea
public class start{
public string datetimew;
}
Now, just parse the JSON before you run it through the deserializer.
string newjsondata = jsonData.replace('"dateTime"','"datetimew"');
JSONParser parser = JSON.createParser(newjsondata);
while (parser.nextToken() != null) {
...
}
Use string.replace() function and replace keys named dateTime with something like dateTime__x and then you can parse using Json.deserialize if you have converted your json to apex using json to apex convertor app on heruko platform
http://json2apex.herokuapp.com/
The above link points to an app that will convert Json into apex class and then you can use Json.serialize to parse json into apex class structure.

GSON deserialization problem

I am having a deserialization problem using the GSON library.
The following is the JSON code which I try to deserialize
{"response": {
"#service": "CreateUser",
"#response-code": "100",
"#timestamp": "2010-11-27T15:52:43-08:00",
"#version": "1.0",
"error-message": "",
"responseData": {
"user-guid": "023804207971199"
}
}}
I create the following classes
public class GsonContainer {
private GsonResponse mResponse;
public GsonContainer() { }
//get & set methods
}
public class GsonResponse {
private String mService;
private String mResponseCode;
private String mTimeStamp;
private String mVersion;
private String mErrorMessage;
private GsonResponseCreateUser mResponseData;
public GsonResponse(){
}
//gets and sets method
}
public class GsonResponseCreateUser {
private String mUserGuid;
public GsonResponseCreateUser(){
}
//get and set methods
}
After calling the GSON library the data is null. Any ideas what is wrong with the classes?
Thx in advance for your help ... I assume it's something trivial ....
#user523392 said:
the member variables have to match exactly what is given in the JSON response
This is not the case.
There are a few options for specifying how Java field names map to JSON element names.
One solution that would work for the case in the original question above is to annotate the Java class members with the #SerializedName to very explicitly declare what JSON element name it maps to.
// output: [MyObject: element=value1, elementTwo=value2]
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.SerializedName;
public class Foo
{
static String jsonInput =
"{" +
"\"element\":\"value1\"," +
"\"#element-two\":\"value2\"" +
"}";
public static void main(String[] args)
{
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
MyObject object = gson.fromJson(jsonInput, MyObject.class);
System.out.println(object);
}
}
class MyObject
{
String element;
#SerializedName("#element-two")
String elementTwo;
#Override
public String toString()
{
return String.format(
"[MyObject: element=%s, elementTwo=%s]",
element, elementTwo);
}
}
Another approach is to create a custom FieldNamingStrategy to specify how Java member names are translated to JSON element names. This example would apply the same name mapping to all Java member names. This approach would not work for the original example above, because not all of the JSON element names follow the same naming pattern -- they don't all start with '#' and some use camel case naming instead of separating name parts with '-'. An instance of this FieldNamingStrategy would be used when building the Gson instance (gsonBuilder.setFieldNamingStrategy(new MyFieldNamingStrategy());).
class MyFieldNamingStrategy implements FieldNamingStrategy
{
// Translates the field name into its JSON field name representation.
#Override
public String translateName(Field field)
{
String name = field.getName();
StringBuilder translation = new StringBuilder();
translation.append('#');
for (int i = 0, length = name.length(); i < length; i++)
{
char c = name.charAt(i);
if (Character.isUpperCase(c))
{
translation.append('-');
c = Character.toLowerCase(c);
}
translation.append(c);
}
return translation.toString();
}
}
Another approach to manage how Java field names map to JSON element names is to specify a FieldNamingPolicy when building the Gson instance, e.g., gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES);. This also would not work with the original example, however, since it applies the same name mapping policy to all situations.
The JSON response above cannot be deserialized by GSON because of the special characters # and -. GSON is based on reflections and the member variables have to match exactly what is given in the JSON response.