We are using Symfony2 FOSRestBundle with JMSSerializerBundle for developing REST APIs to be consumed by mobile developers.
The API response in JSON format returns 'null' as value of properties wherever applicable, which is generating an exception for the 3rd party library being used by mobile developers.
I don't see a solution from JMSSerializerBundle or FOSRestBundle to overwrite the value as per our requirement.
Workaround so far
I can set default value in entity so that the fresh data will have some default value in database, instead of null. But this doesn't work for a one-to-one/many-to-one relationship objects, as those will return null by default instead of blank object.
Any solution to overwrite the json after serialization ?
You can use a custom visitor to do that:
<?php
namespace Project\Namespace\Serializer;
use JMS\Serializer\Context;
use JMS\Serializer\JsonSerializationVisitor;
class BlankSerializationVisitor extends JsonSerializationVisitor
{
/**
* {#inheritdoc}
*/
public function visitNull($data, array $type, Context $context)
{
return '';
}
}
And then, set it to your serializer with the setSerializationVisitor method or in your config file:
# app/config/config.yml
parameters:
jms_serializer.json_serialization_visitor.class: Project\Namespace\Serializer\BlankSerializationVisitor
When using the FOSRestBundle, in your configuration file (generally app/config/config.yml) you can use this settings to avoid having null values:
fos_rest:
serializer:
serialize_null: false
If you want a custom value, you can use the serializer.post_serialize event.
PS: To have all possible options provided by the bundle, type this command:
php bin/console config:dump-reference fos_rest
Related
I'm retrieving data from a Mysql database, and this is done via mapping my entity properties to database fields using Doctrine with annotations as shown in this
image. Retrieving the data is not the problem, but my property name is used as key for the returned data, which is not what i want.
Example:
I have a property gridId (camelCase), which is mapped to a database field called grid_id (snake_case) as shown in the image above. The key for the rows returned for this property will be gridId, and not grid_id, which is desired in my case.
An example of the current situation:
image.
The desired situation:
$grid =
[
grid_block_id = 18
width = 50
width_pixels = 50
]
Changing either the database fields or the property names is not an option in my case.
EDIT
I'm using JMS as serializer. I guess the 4th option of #Jakumi's answer is probably the best option for my use case. Somehow use the serializer to return the property's column name as key for returned values.
My struggle when retrieving data from doctrine is that i have to manually adjust the keys fetched by doctrine as shown in this image as this is how the front-end expects it to be.
so what you're saying is ... you want to actively ignore the object relational mapping (ORM) that the doctrine ORM you're using is providing you and which actually provide the keys exactly the way your entity names them?
I assume there is some good (or not so good) reason for this. Depending on your use case, different solutions may be the best. Options including (but probably very incomplete):
option 1: add a function to the entity
class Grid {
/** all your fields **/
public function toArray() {
return [
'grid_id' => $this->gridId,
// ...
];
}
}
option 2: don't use the orm
add a function in your GridRepository like:
function getRawAll() {
$conn = $this->getEntityManager()->getConnection();
$_result = $conn->query('SELECT * FROM grid');
$results = [];
while($row = $_result->fetch()) {
$results[] = $row;
}
return $results;
}
and similar. Those are obviously circumventing the ORM. The ORM is for retrieving objects, and those have specified fields.
option 3: return the given array back to the unmapped state
use the EntityManager's getClassMetadata (ClassMetadataInfo->fieldMapping) to fetch the mapping for your fields, and "revert" the renaming.
This is probably slightly better than option 1 to some degree, since it doesn't have to be updated.
option 4: use a serializer that does your property name translation.
since you're apparently already using the jms serializer, the SerializedName annotation can probably help, although the default appears to be snake case, but maybe somewhere it's overridden? you might want to check your configuration ...
How to set default data format for a component in Apache Camel?
I have a number of routes interacting with different ActiveMQ queues. At the moment all of them look like
from("...")
.process(...)
.marshal().json() // (1)
.to("activemq:queue:...");
or
from("activemq:queue:...")
.unmarshal().json() // (2)
.process(...)
.to("...");
I would like to replace lines (1) and (2) with either component or context level configuration. Basically saying only once 'message payload going through ActiveMQ has to be a JSON string'.
I don't like to add any additional routes, processors, headers, URI parameters, etc.
Ideally, it would be applicable for other components and formats besides ActiveMQ and JSON
You could marshall/unmarshall using a named reference to a data format that you can define once (here as "myDefaultFormat") in your Camel Registry:
from("activemq:queue:...")
.unmarshal(myDefaultFormat)
This way, you dont have to repeat .json() everywhere
(but ok, you have yet to repeat the named reference :-$ )
Using interceptors (Based on Claus Ibsen's comment)
new RouteBuilder() {
#Override
public void configure() throws Exception {
// interceptors
interceptSendToEndpoint("activemq:queue:*")
.marshal()
.json();
interceptFrom("activemq:queue:*")
.unmarshal()
.json();
// routes
from("...")
.process(...)
.to("activemq:queue:...");
from("activemq:queue:...")
.process(...)
.to("...");
}
}
Notes:
interceptors have to be defined before any routes in RouteBuilder. Otherwise IllegalArgumentException is thrown explaining situation.
interceptors are not shared and have to be defined in each RouteBuilder.
In Fat Free Framework, I am trying to figure out how to specify a query string in the route call or the routes.ini file.
I want to be able to decode a route specified like this
http://example.com/search?category=22&term=wide
Note if possible I'd like to have a varying number of elements in the query string.
Thanks in advance
The framework doesn't allow to route query strings, only paths.
So, either you modify your routes to include the parameters in the URI path:
;routes.ini
GET /search/#category = MyController->searchByCategory
GET /search/#category/#term = MyController->searchByCategoryAndTerm
(which requires a strict order of the parameters)
Or you route everything to one same controller and parse the query string there:
;routes.ini
GET /search = MyController->search
class MyController {
function search(\Base $f3) {
$category=$f3->get('GET.category);
$term=$f3->get('GET.term');
//etc.
}
}
If you're implementing a search form, the second solution looks the most appropriate.
I have built a MVCPortlet that runs on Liferay 6.2.
It uses a PortletPReferences page that works fine to set/get String preferences parameters via the top right configuration menu.
Now I would need to store there a String[] instead of a regular String.
It seems to be possible as you can store and get some String[] via
portletPreferences.getValues("paramName", StringArrayData);
I want the data to be stored from a form multiline select.
I suppose that I need to call my derived controller (derived from DefaultConfigurationAction) and invoke there portletPreferences.setValues(String, String[]);
If so, in the middle, I will neeed the config jsp to pass the String[] array to the controller via a
request.setAttribute(String, String[]);
Do you think the app can work this way in theory?
If so, here are the problems I encountered when trying to make it work:
For any reason, in my config jsp,
request.setAttribute("paramName", myStringArray);
does not work ->
actionRequest.getAttribute("paramName")
retrieves null in my controller
This is quite a surprise as this usually works.
Maybe the config.jsp works a bit differently than standard jsps?
Then, how can I turn my multiline html select into a String[] attribute?
I had in mind to call a JS function when the form is submitted.
this JS function would generate the StringArray from the select ID (easy)
and then would call the actionURL (more complicated).
Is it possible?
thx in advance.
In your render phase (e.g. in config.jsp) you can't change the state of your portlet - e.g. I wouldn't expect any attributes to persist that are set there. They might survive to the end of the render phase, but not persist to the next action call. From a rendered UI to action they need to be part of a form, not request attributes.
You can store portletpreferences as String[], no problem, see the API for getting and setting them
I think maybe you can use an array in client side, and you can update the javascript array, when user is selecting new values.
So you have the javascript array, then when user click on the action, you can execute the action from javascript also, something like this:
Here "products" is the array with your products.
A.io.request(url, {type: 'POST',
data: {
key: products
},
on: {
success: function(event, id, obj) {
}
}
});
From Action methd you can try to get the parameter with:
ParamUtil.getParameterValues(request,"key");
My problem is, that my Spring-Boot Actuator endpoint for env actually replaces some properties with starts like this:
"applicationConfig: [classpath:/config/application.properties]" : {
"rest.baseurl" : "http://85.214.247.80:9912",
"projectKey" : "******",
And I have no clue why. I did not have any hint in my application thats he should hide it. I guess there is some heuristic to hide it based on the property name.
any Ideas how to avoid the masking?
By default the /env endpoint will hide the value of any property with a key that, ignoring case, ends with password, secret, or key. You can customize this using the endpoints.env.keys-to-sanitize property. The value of this property should be a comma-separated list of suffixes or regexes to match against property names. For example, if you don't care about keys ending in key you could set it to:
endpoints.env.keys-to-sanitize=password,secret
This is what the documentation says:
endpoints.env.keys-to-sanitize=password,secret,key,token,.credentials.,vcap_services
Keys that should be sanitized. Keys can be simple strings that the property ends with or regex expressions.
Now from Spring boot version 3, by default the value of all properties are hidden.
To display the value in /env endpoint, below configuration needs to be added in application.properties file.
management.endpoint.env.show-values=ALWAYS
Valid values for the Property is as below
ALWAYS
NEVER
WHEN_AUTHORIZED
You can do it as #Andy Wilkinson mention. But you will see "endpoints.env.keys-to-sanitize" property with value "password,secret" in the applicationConfig section of /env endpoint.
To avoid this you can set the property using code as well:
public class MyApp {
#Autowired
private EnvironmentEndpoint envEndPnt;
#PostConstruct
public void initApplication() {
envEndPnt.setKeysToSanitize("password","secret");
}
}
So once all the initializations are done and the initApplication is called you will have the EnvironmentEndPoint to which you set the property manually.
The property to set now is management.endpoint.env.keys-to-sanitize. To reveal all properties just set it to nothing, e.g. management.endpoint.env.keys-to-sanitize=
For Spring Boot 3, put in pom.xml management.endpoint.env.show-values=ALWAYS