Array to string conversion in EasyAdmin 3 (Symfony 5) - json

I'm trying to display a json array on the EasyAdmin detail page. I read here Is there a way to represent a JSON field in EasyAdmin 3? that you can use ArrayField in EasyAdmin 3 to display a json array, which would make sense to me as that is the only field in EasyAdmin that could display it so I added it like this:
public function configureFields(string $pageName): iterable
{
return [
ArrayField::new('status', $this->translator->trans('form.label.status'))->onlyOnDetail(),
];
}
But it gives me this error:
An exception has been thrown during the rendering of a template ("Notice: Array to string conversion"). Do I need to add something else to it or does it not work at all?

change "status" to a multiplicity "statuses"
Worked for me with changing "print" to "prints"

I found a workaround that resolved the issue in my situation where I wanted just to show JSON on details page
So in your entity add a get function as an unmapped field as indicated in the official documentaiton
https://symfony.com/bundles/EasyAdminBundle/current/fields.html#unmapped-fields
for example
public function getJsonField() {
return json_encode($this->yourEntityJsonAttribute);
}
then in configureFields function in your CrudController add your field like this
TextAreaField::new('jsonField')->onlyOnDetail()
You can also read the json attribute and generate an HTML string in the getJsonField function then in configure field just add renderAsHtml in th field like this
TextAreaField::new('jsonField')->onlyOnDetail()->renderAsHtml()
Wish this suits your case too, Good luck

Related

Why I Can't Write Objects in <li> Tag

When I writing my JSON data to HTML tag it's writing but don't write object. It's write [object Object]:
○Data1 ○wash dishes ○[object Object]
○find some break ○[object Object]
I'm trying to do lists with pointing JSON database but it's looks like that. I'm calling my JSON with that code:
var db_note = objpick(data);
db_note.date.forEach(function(element) {
tabledatednote.insertAdjacentHTML( 'beforeend',"<li>" + element + " </li>");
/* I just writed to this part because is just changing "no_date.>date<" part while displaying other JSONs */
});
objpick.js is an external file
function objpick(data){
for(i in data){ var result = data[i] }
return result
};
and there is my JSON database
{
"nodate": ["wash dishes", "find some bread"],
"date": [{"01/01/2077" : "Cyberpunk Meet"}, {"25/05/2005" : "Buney?"}],
"bookmark" : ["Data1"]
}
Ultimately what's being displayed is a string. So the code converts whatever you want to display to a string. For simple values, this conversion is easy. It's consistent and obvious what the resulting string is for a single value.
But objects are not simple values. They are potentially complex. And unless otherwise defined on your object(s), the default string representation for an object is: [object Object]
Some of the things you are display are values:
"find some bread"
But some of them are objects:
{"25/05/2005" : "Buney?"}
For the objects, you'd need to tell the code how to display it. Some options I can think of are:
Manually. For example, check if a certain property exists on the object and, if it does, display that property's value.
JSON-encode the object and display the resulting JSON string.
Override .toString() on your object(s).
Which you choose is up to you, and for the same reason that you're seeing the current default behavior... Because only you know how you want/expect that object to be displayed.

How to print an object as JSON to console in Angular2?

I'm using a service to load my form data into an array in my angular2 app.
The data is stored like this:
arr = []
arr.push({title:name})
When I do a console.log(arr), it is shown as Object. What I need is to see it
as [ { 'title':name } ]. How can I achieve that?
you may use below,
JSON.stringify({ data: arr}, null, 4);
this will nicely format your data with indentation.
To print out readable information. You can use console.table() which is much easier to read than JSON:
console.table(data);
This function takes one mandatory argument data, which must be an array or an object, and one additional optional parameter columns.
It logs data as a table. Each element in the array (or enumerable property if data is an object) will be a row in the table
Example:
first convert your JSON string to Object using .parse() method and then you can print it in console using console.table('parsed sring goes here').
e.g.
const data = JSON.parse(jsonString);
console.table(data);
Please try using the JSON Pipe operator in the HTML file. As the JSON info was needed only for debugging purposes, this method was suitable for me. Sample given below:
<p>{{arr | json}}</p>
You could log each element of the array separately
arr.forEach(function(e){console.log(e)});
Since your array has just one element, this is the same as logging {'title':name}
you can print any object
console.log(this.anyObject);
when you write
console.log('any object' + this.anyObject);
this will print
any object [object Object]

Json element value returning null though found in request body

I am trying to pass some json data
{
"name":"srk",
"age":25,
"interests":"programming"
}
through ajax and fetching the request body into play controller as shown below.
#BodyParser.Of(BodyParser.Json.class)
public Result example(){
JsonNode jsonNode = request().body().asJson();
Logger.info("requestBody = "+ jsonNode);
}
The above logger prints the request payload sent during the request exactly
like below:
{"name": "srk", "age":25, "interests" : "programming"}
But when I try to print age they it is showing up as null.
String age = jsonNode.findPath("age").textValue();
Logger.info("age= "+ age);
This is printing age= null
Any ideas would help.
As I cannot yet comment, I'm writing a proper answer in the name of #DBug.
#srk, please choose a correct answer and mark the question as solved =)
The JSonNode .textValue() method seems not to automatically convert between content types. Since age is a numeric field, the textValue() is actually null. There are two possible solutions:
You can retrieve the node content as the correct type with:
jsonNode.findPath("age").asInt();
You can retrieve the node content as a String with either:
jsonNode.findPath("age").asText();
//or
jsonNode.findPath("age").toString();
I went looking for the documentation here: com.fasterxml.jackson.databind.JsonNode
Direct link to textValue() description.
Direct link to asInt() description.
Direct link to asText() description.
You should use jsonNode.get("age").asInt() to get the value instead of findPath

Deep JSON serialization in Grails not working

I have an object structure like so:
class Message {
static mapWith="mongo"
static embedded = ['to', 'author', 'comments', 'tags']
ObjectId id
Set<ObjectId> to
Author author
String text
List<Comment> comments
Set<String> tags
Date postedOn
Date lastEditOn
}
class Comment {
Author author
String text
int thumbsUp = 0
int thumbsDown = 0
Date postedOn
Date lastEditOn
}
And the following code for serialization to JSON
render Message.findStreamFor( session.user, groups, 0, 20 ) as JSON
However, none of the embedded collections are being serialized. They are just missing. I've tried adding the following to my Config.groovy to make it deeply serialize by default:
grails.converters.json.default.deep=true
But that doesn't seem to change anything. I've seen the objects are populated from MongoDB in the debugger, but it just doesn't make it to the JSON serialized output. How can I fix this?
UPDATE
Ok I've figured out a bit more by debugging the code. Inside the DefaultGrailsDomainClass.getPersistentProperties() it doesn't return the collections as properties when called. And JSON serializer never visits them. On line 103 of DomainClassMarshaller is the call to getPersistentProperties which isn't returning all properties.
GrailsDomainClassProperty[] properties = domainClass.getPersistentProperties();
Seems like this is a bug! How has no one else ever found this?
You could to use GSON plugin. It didn't help me in a similar problem but it may help you.
This plugin was written to overcome nested object deserialization problem in standard Grails JSON converter, but it may also be better at serializing them.

Is there a way to add an additional field to Grails JSON response?

I want every JSON response to post-request to contain a field success. What's the best way to add this field there?
I use code like this to generate JSON responses:
try {
def entity = myService.saveEntity(arg1,arg2)
render entity as JSON //I want to add artificial field 'success = "yes"' here
} catch (ValidationException e) {
render parseErrors(e.errors) as JSON //field 'success = "no"' here
}
I just struggled with this exact issue this week. I wanted to send back a domain class as JSON but at the same time add an 'errorMessage' property that would potentially contain additional information.
Turns out that when using as JSON in grails it sends back a converter object, but its possible to turn that converter instance into a jsonObject using JSON.parse() which we can easily add new values to.
def jsonObject = JSON.parse((entity AS JSON).toString())
jsonObject.put("success", "yes")
render jsonObject as JSON
I think there are a couple of different approaches but this ended up being the easiest for me since I already have custom converters for most of my domain classes and I didn't want to add any other transient properties to my domain object.
Could you return a map containing the success field, and the object wrapped inside a separate variable:
try {
def entity = myService.saveEntity(arg1,arg2)
render [ success:'yes', val:entity ] as JSON
} catch (ValidationException e) {
render [ success:'no', val:parseErrors(e.errors) ] as JSON
}
Not tested it mind...
You can register your own JSON marshaller (at BootStrap.groovy, for example), like:
JSON.registerObjectMarshaller(MyEntity) { MyEntity it ->
return [
someField : it.someField, // you should specify fields for output, or put all '.properties'
success : true // as I understand you always have 'true' for real entity
]
}
where MyEntity is your class you want to use