I am using Grails 2.1 to render JSON as part of a RestFul API I created. The Domain class, based on a SqlServer table, looks like this:
String firstName
String lastName
String officialAddress1
String officalAddress2
String preferredAddress1
String preferredAddress2
(etc.). . .
Which returns JSON similar to this:
{
"firstName": "Joe",
"lastName": "Hill",
"officialAddress1": "1100 Wob Hill",
"officialAddress2": "Apt. # 3",
"preferredAddress1": "1100 Wobbly Lane.",
"preferredAddress2": "Apartment 3."
}
It is working fine but the client wants me to nest the results in this fashion:
{
"firstName": "Joe",
"lastName": "Hill",
preferredAddress {
"preferredAddress1": "1100 Wobbly Lane.",
"preferredAddress1": "Apartment 3."
},
officialAddress {
"officialAddress1": "1100 Wob Hill",
"officialAddress2": "Apt. # 3"
}
}
My question is since the domain class, and the database, are not structure in a way to return this type of nested result how can I easily change this in my returned JSON? Do I have to abandon my way of just regurgitating the JSON based on the database/domain object and do a custom converter of some kind?
i'm new to this stackoverflow thing and i hope i will not mess it but i think i know what you need. in your bootstrap.groovy file you find "def init = { servletContext -> " line
put in there something like this:
JSON.registerObjectMarshaller(YourDomainName) {
def returnArray = [:]
returnArray['firstName'] = it.firstName
returnArray['lastName'] = it.lastName
returnArray['preferredAddress'] = [it.preferredAddress1 ,it.preferredAddress2]
returnArray['officialAddress'] = [it.officialAddress1 ,it.officialAddress2]
return returnArray
}
now when you use the render with JSON as you did grails will look in bootstrap and
render the domain as you asked.
hope this helps
The posted answer was correct. I just wanted to add the slight change I made to get the exact results I needed:
Thanks! That did it. I originally that it would not work exactly how I needed it but I was wrong. I changed the syntax slightly to get the results I needed.
returnArray['preferredAddress'] = [address1: it.preferredAddress1?.trim(),
address2: it.preferredAddress2?.trim(),
address3: it.preferredAddress3?.trim(),
city: it.preferredCity,
state: it.preferredState,
postCode: it.preferredPostCode,
country: it.preferredCountry
]
Related
So this feels like an interview question but it's not. Before you mark this as duplicate, please know I've looked at other answers: 1. there's no scala solution, 2. my case needs a way to mask more than one matched key.
I have a def that makes all my http requests. After I send the request, I log the request and response. Since these requests have a JSON body that may or may not have a sensitive field like these:
challengeAnswer
currPassword
password
answer
oldPassword
I'd like to create a universal JSON scanner that DEEP scans the keys of a given JSON object and masks the value if it matches one of these regexes case insensitively:
.*answer.*
.*password.*
Sample Request Body:
{
"resetPassQuestion1": "I pity the ...?",
"resetPassAnswer1": "Foo",
"resetPassQuestion2": "Let's grab a pint at the ...?",
"resetPassAnswer2": "Bar",
"firstname": "John",
"lastname": "Doe",
"email": "john.doe#example.com",
"loginId": "jdoe666",
"password": "Secret1"
}
I need to mask Foo, Bar, and Secret1 in this example with 5 asterisks such when I print in the logs, it will print:
{
"resetPassQuestion1": "I pity the ...?",
"resetPassAnswer1": "*****",
"resetPassQuestion2": "Let's grab a pint at the ...?",
"resetPassAnswer2": "*****",
"firstname": "John",
"lastname": "Doe",
"email": "john.doe#example.com",
"loginId": "jdoe666",
"password": "*****"
}
I am not finding examples of case match that's insensitive. What's a good clear way to tackling this problem with easy to read code.
So I solved it using LiftJson's transform.
import net.liftweb.json.JsonParser
import net.liftweb.json.Printer.compact
import net.liftweb.json.JsonAST._
private def maskPasswords(jsonStr: String): String = {
Try(JsonParser.parse(jsonStr)) match {
case Success(json) => {
compact(
render(
json.transform {
case JField("password",_) => JString("*****")
case JField("oldPassword",_) => JString("*****")
case JField("resetPassAnswer2",_) => JString("*****")
case JField("resetPassAnswer1",_) => JString("*****")
}
)
)
}
case _ => "**** JsonParsing Failed! **** Masking Everything *****"
}
}
It's not perfect since every new field that I want to mask, I would have to add a new line here but it works well enough for me for now.
I have below JSON response coming from API, in which 104 and 2 are dynamically changing and I have these values already set in environmental varibales, e.g. {location_id} = 2, {account_id} = 104
Can anyone help on how to parse JSON and get the location object based on environment variable value for location id in postman tests section
{
"104": {
"2": [
{
"FirstName": "John",
"LastName": "McClain",
"Phone": "1234567890"
}
],
"3": [
{
"FirstName": "Rita",
"LastName": "Maria",
"Phone": "3092432345"
}
]
}
}
This is a very horrible and flaky way to 'test' the values from the response JSON in the question. This assumes that the environment vars that were set in the previous request were account_id = 104 and location_id = 3. This does a hardcoded check to see that the FirstName property in that object, equals 'Rita'.
pm.test('Get the values', () => {
var jsonData = pm.response.json()[pm.environment.get('account_id')][pm.environment.get('location_id')]
pm.expect(jsonData[0].FirstName).to.equal('Rita')
})
It's difficult to tell what you actually want to do with the data and this test isn't something that I would use but if you just wanted an insight into how you would parse the data based on some environment vars this is at least a starting point.
If more information is provided, I will update my answer to reflect this.
In node.js my program app.js, i am defining array like this
var myList = [["SAHRUKH",47.49,"HIT"],["SALMAN",47.3,"FLOP"]];
console.log (myList)
It is giving output but i want an external JSON file to supply the parameter of myList array instead of me defining it hardcore
i have prepared a JSON file named ppm.json and change my code to
var myList = JSON.parse(fs.readFileSync('ppm.json', 'utf8'));
console.log (myList[1])
my ppm.json is this
{
"hero": "SAHRUKH",
"age": "47.49",
"lastpict": "HIT"
}
it giving me output as undefined in console. what is the problem. pls help.
Without more requirements it's hard to give a definitive answer, but one thing you can do:
app.js
var myList = require('./my_list.json');
console.log(myList);
my_list.json
[["SAHRUKH",47.49,"HIT"],["SALMAN",47.3,"FLOP"]]
You can use require() to load both JSON and JavaScript files.
For example,
myFile.json:
[["SAHRUKH",47.49,"HIT"],["SALMAN",47.3,"FLOP"]]
app.js:
var myList = require( './myFile.json' );
console.log (myList)
You're accessing your item wrong. You don't have an array you have an object.
Access your heros age like this:
myList['age']
You might also consider changing your file to look like this:
{
"SAHRUKH" : {
"age" : "47.49",
"lastpict" : "HIT"
}
}
In which case you'd get your hero's age like:
myList.SAHRUKH.age;
//Or Equivalently
myList['SAHRUKH']['age']; //The dot notation above is preferred though!
Or this
{ "heros" : [
{
"name" : "SAHRUKH",
"age" : "47.49",
"lastpict" : "HIT"
}
]}
In which case you'd get at age like:
myList.heros[0].age;
If you adjust your ppm.json file to look like:
[{
"hero": "SAHRUKH",
"age": "47.49",
"lastpict": "HIT"
}]
It should drop in and work directly. If you wanted to include multiple heroes, it would look like:
[
{
"hero": "SAHRUKH",
"age": "47.49",
"lastpict": "HIT"
},
{
"hero": "SALMAN",
"age": "47.3",
"lastpict": "FLOP"
}
]
Your resulting myList should be an array in the example you provided, with entry 0 being the first hero object (SAHRUKH) and 1 being the second, and so on.
I have created a JSON object using VB.NET
{
"MasDatos": {
"Cosas": "Yo que se",
"MasCosas": "Ni idea",
"OtroArray": [
"Cosa 1",
"Cosa 2",
"Cosa 3"
]
},
"nombre": "Person Name",
"apellidos": "Second Name",
"edad": 19,
"Gustos": [
"Gusto 1",
"Gusto 2"
]
}
I Send this code to my WCF Service on "POST" Method. I can read all variables, for example.
If i want to read "edad" i can do something like this in my wcf service method...
public String readParameter(String edad){
return edad;
}
above code works. But I CANT read "MasDatos" values. That is a Dictionary. But im not able to retrieve it.
If you see, "Gustos" is an array. I can read it doing this
public string readValue(array Gustos){
//Logical stuff
}
i've tried doing this to read "MasDatos"
public string readDicto(List<String,Object> myNewDictionary){
return somestring;
}
but myNewDictionary is null everytime...
Please forgive my horrible english. I hope someone can help me =)
Thanks in advance!!
Well, answer is quite simple.
Use classes with [datacontract] and [datamember] tags to map complex json objects
Is there a standardized way to store classes in JSON, and then converting them back into classes again from a string? For example, I might have an array of objects of type Questions. I'd like to serialize this to JSON and send it to (for example) a JavaScript page, which would convert the JSON string back into objects. But it should then be able to convert the Questions into objects of type Question, using the constructor I already have:
function Question(id, title, description){
}
Is there a standardized way to do this? I have a few ideas on how to do it, but reinventing the wheel and so on.
Edit:
To clarify what I mean by classes: Several languages can use classes (JAVA, PHP, C#) and they will often communicate with JavaScript through JSON. On the server side, data is stored in instances of classes, but when you serialize them, this is lost. Once deserialized, you end up with an object structure that do not indicate what type of objects you have. JavaScript supports prototypal OOP, and you can create objects from constructors which will become typeof that constructor, for example Question above. The idea I had would be to have classes implement a JSONType interface, with two functions:
public interface JSONType{
public String jsonEncode();//Returns serialized JSON string
public static JSONType jsonDecode(String json);
}
For example, the Question class would implement JSONType, so when I serialize my array, it would call jsonEncode for each element in that array (it detects that it implements JSONType). The result would be something like this:
[{typeof:"Question", id:0, title:"Some Question", description:"blah blah blah"},
{typeof:"Question", id:0, title:"Some Question", description:"blah blah blah"},
{typeof:"Question", id:0, title:"Some Question", description:"blah blah blah"}]
The javascript code would then see the typeof attribute, and would look for a Question function, and would then call a static function on the Question object, similar to the interface above (yes, I realize there is a XSS security hole here). The jsonDecode object would return an object of type Question, and would recursively decode the JSON values (eg, there could be a comment value which is an array of Comments).
You'll have to create your own serializer which detects Question (and other classes) and serializes them as constructor calls instead of JSON object notation. Note that you'll need a way to map an object to a constructor call. (Which properties come from which parameters?)
Everyone else: By classes he means functions used as constructors; I assume that he's trying to preserve the prototype.
Have you looked at JSON.NET? It can serialize/de-serialize .NET objects to JS and vice-versa. It is a mature project and I highly recommend it.
Also, if you could change the definition of your 'Question' function to take one object with properties instead of taking separate arguments, you can do something like this:
Working Demo
function Question(args)
{
this.id = args.id;
this.text = args.text;
}
Question.prototype.alertText = function() { alert(this.text); };
$(document).ready(
function()
{
var objectList =
{
'list' : [
{ 'id' : 1, 'text' : 'text one' }
,{ 'id' : 2, 'text' : 'text two' }
,{ 'id' : 3, 'text' : 'text three'}
],
'type' : 'Question'
};
var functionName = objectList['type'];
var constructor = window[functionName];
if(typeof constructor !== 'function')
{
alert('Could not find a function named ' + functionName);
return;
}
var list = objectList['list'];
$.each(list,
function()
{
var question = new constructor(this);
question.alertText();
}
);
}
);
On a side note, please prefix your .NET Interfaces with 'I' e.g. it should be IJsonType and not JsonType.
typeof is a keyword so specify the property name in quotes if you want to use it.
It's highly dangerous, but eval can process any text and execute it.
http://www.w3schools.com/jsref/jsref_eval.asp
But DON'T use it. May do something like pass over the params you want to pass into the constructor as a JSON object and call the constructor with it...
function Question({"id" : "val", "title", "mytitle", "description" : "my desc"}){
...
}
This might be useful.
http://nanodeath.github.com/HydrateJS/
https://github.com/nanodeath/HydrateJS
Use hydrate.stringify to serialize the object and hydrate.parse to deserialize.
Assuming you are using a Javascript client and a REST api backend and you are looking to define the rules for encoding a Method as JSON, you should probably consider using graphQL.
You could also look at my draft Specificaton for JSON-ND - that may give you simple representation: eg
Where the server publishes this specification:
{
"Question:POST(id:integer, title:string, description:string):string" :
"https://my.question.com:999/question"
}
Or perhaps a little less "C" style
{ "QuestionParam:Interface"[
"id:integer",
"title:string",
"description:string"
],
"Question:POST(QuestionParam[0,]):string" :
"https://my.question.com:999/question"
}
This means you can POST the following to https://my.question.com:999/question
{
"questions:Question": [
{id:0, title:"Some Question 1", description:"blah blah blah"},
{id:1, title:"Some Question 2", description:"blah blah blah"},
{id:2, title:"Some Question 3", description:"blah blah blah"}
]
}
And the server would respond with something like:
[
"answer 1",
"answer 2",
"answer 3",
]
You might even define a better return type say "Answer"
{
"Answer:Interface"[
"id:integer",
"answer:string"
],
"Question:POST(id:integer, title:string, description:string):Answer" :
"https://my.question.com:999/question:URI"
}
And the server would return:
{ "answers:Answer" :[
{"id":0, "answer":"Answer 1"},
{"id":1, "answer":"Answer 2"},
{"id":2, "answer":"Answer 3"}
]
}
on the client side, implement a JSON-ND interpreter similar to the example:
, include a Fetch call and you could use something like:
var questions = {
"questions:Question": [
{id:0, title:"Some Question 1", description:"blah blah blah"},
{id:1, title:"Some Question 2", description:"blah blah blah"},
{id:2, title:"Some Question 3", description:"blah blah blah"}
]
}
var answers = JSON_ND_Stringify(questions) ; //of course use an async call here