Error parsing json with unexpected properties - how to relax parsing rules? - jackson

I have an API hosted/written in DropWizard. It consumes JSON and works well
#POST
public void somePost(SomeObject object)
Where SomeObject is a pojo. Jackson deserialises JSON into the object without a problem.
To future proof the "calling code" that uses this API I started to add some properties that are not yet in SomeObject. However (presumably Jackson) now throws an "error parsing json" error.
I would like to relax the rules a bit so that Jackson is a bit more tolerant about fields that it doesn't recognise in the incoming JSON (GSON does that by default). I tried #JsonIgnoreProperties class level annotation but no luck.
Thanks in advance.

You said that you tried #JsonIgnoreProperties. Have you tried it like this?
#JsonIgnoreProperties(ignoreUnknown = true)
Tested above one and it should work.

Another option is to just globally allow any and all unknown properties by disabling DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES. It may be dangerous in just ignoring everything that does not map, but for "Open Content" style usage it works great.

Related

Deserializing Media field fails in Piranha CMS

Modifying Piranha for 'headless' scenario: I separated the api into its own REST API, and the MVC into its own UI that calls the REST API. Mostly it works well, but now an obstacle. My REST API serializes the result from the Piranha api, and my MVC web deserializes it into a Piranha StandardPage type. This works for all fields except Media, which is always null. Using newtonsoft.Json.
The Media property is defined in Piranha.Extend.Fields.MediaFieldBase with internal set, which explains why I can't deserialize into it. So I added a [JsonProperty] attribute to the Media property. Once I did this, then the Media field was correctly deserialized by the MVC, and images appeared.
But then I found this broke something else: in the manager, when I try to save a page with a Hero image, the Save buttons spins, stops as though it succeeded, but the toast never appears saying success. I set Debug logging for Microsoft.AspNetCore.Mvc.Infrastructure, and see there's a model state error when this happens:
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2]
Executed controller factory for controller Piranha.JA.Manager.Controllers.PageApiController (Piranha.JA.Manager)
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ModelStateInvalidFilter[1]
The request has model state errors, returning an error response.
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
Request was short circuited at action filter 'Microsoft.AspNetCore.Mvc.Infrastructure.ModelStateInvalidFilter'.
I can debug into the PageApiController for most operations, but when Save executes none of the breakpoints are hit.
I also tried just removing the internal accessor from set (and removing [JsonProperty]) and got the same behavior: can deserialize Media ok but trying to save page with a Hero from manager gives model state error.
Would love to write up some documentation on how to go headless if we can solve this.
We've been debugging this one for a few days, can anyone help?
In the branch I pushed I actually changed the accessor to public, so you shouldn’t need the additional attribute. This is also merged to master and will be released in 8.3.
Regards
I posted this on the Piranha CMS github and one of its authors, Hakan Edling, answered in just a few hours:
"The root issue is that when a new item is selected in the manager in the media picker, the media model that is assigned contains a formatted string size "xxx kb". When ASP.NET tries to deserialize this into a long it fails.
So changing the following line in the .vue components for the media-based fields:
this.model.media = media;
to
this.model.media = {
id: media.id,
folderId: media.folderId,
type: media.type,
filename: media.filename,
contentType: media.contentType,
publicUrl: media.publicUrl,
};
Resolves the serialization error in the manager when the Media property is public.. I'll push this fix to a new branch so you can test it."
And soon after,
"Please test with the branch https://github.com/PiranhaCMS/piranha.core/tree/features/make-mediafield-media-public"
I still must add the [JsonProperty] attribute to the Media field in MediaFieldBase class, so my deserializer can access the internal set method. Hakan's fix makes it so this attribute doesn't break the manager.
Thank you for your quick response Hakan, you rock!

ActorSystem.Create() ignores config

I am trying to instantiate an actor system with non-default behaviour (e.g. clustering or remoting) but no matter what I do the ActorSystem always ends up with default configuration. The config object and settings object appear correct (e.g. actor.provider == cluster) but the actual run-time object always has defaults.
I've tried constructing the config many different ways. With App.config cdata and by manually parsing a config file with ConfigurationFactory and passing it in to Create. I had the problem with 1.4.3 and with 1.3.17.
I downloaded the Akka source code and debugged it. Stepping through the Create method I found that the root HoconObject's items dictionary contains 2 entries with the key "akka". One entry is mine, the other looks like a fallback. The getter method resolves the fallback.
I guess there is some weird string formatting happening...
[Update] There seems to be confusion about what is actually happening. Here is a screen-shot of what HoconObject looks like when it works:
In the screen-shot you can clearly see a single entry in the Items dictionary for "akka" that is set to "provider=cluster", which isn't the default and is coming from the config file. The previous screen-shot shows 2 entries, one of which is "provider=cluster" and the other is clearly the default that Akka injects. Both key = "akka". The bug causes Akka to select the default rather than the override.
I understand that Hocon allows overrides from defaults but that isn't what's happening. Again, if you look at the source code for HoconObject you'll see the screen-shot is of a plain .Net dictionary called 'Items' and the TryGetValue is the .Net implementation... not a Hocon implementation.
This is obviously a parsing bug that cases Akka to behave incorrectly and throw no exceptions.
I don't have enough reputation to post my question as a comment.
Do you have a code I can use to replicate the problem? A code snippet of how you build your config would be fine.
I downloaded the Akka source code and debugged it. Stepping through the Create method I found that the root HoconObject's items dictionary contains 2 entries with the key "akka". One entry is mine, the other looks like a fallback. The getter method resolves the fallback.
Yes, this is the actual behavior of a HoconValue. a HoconValue is a list of value fragments that will be converted into a proper data type when you call the appropriate getter function. For example, the HoconValue instance that you see in your debug session is actually 2 HoconObject fragments, and the proper merged object can be retrieved by calling the GetObject() function of that HoconValue instance.

Restlet client interface class

Restlet looks cool, but Im sorry, I'm just banging my head all day due to lack of documentation on a simple client.
I've managed to crib some useful stuff from
http://restlet.org/learn/guide/2.1/core/resource/client
But there is just nothing that actually works as a full download (which would be nice). For example is the Customer here a pojo only ? or must it implement Serializable (I think it must).
My specific issue is as follows:
I have some code which makes a call to a URL and gets back this:
{"result":"success","data":{"last_local":{"value":"889.66000","value_int":"88966000","display":"$889.66","display_short":"$889.66","currency":"USD"},"last":{"value":"889.66000","value_int":"88966000","display":"$889.66","display_short":"$889.66","currency":"USD"},"last_orig":{"value":"889.66000","value_int":"88966000","display":"$889.66","display_short":"$889.66","currency":"USD"},"last_all":{"value":"889.66000","value_int":"88966000","display":"$889.66","display_short":"$889.66","currency":"USD"},"buy":{"value":"889.00000","value_int":"88900000","display":"$889.00","display_short":"$889.00","currency":"USD"},"sell":{"value":"889.66000","value_int":"88966000","display":"$889.66","display_short":"$889.66","currency":"USD"},"now":"1388846889233438"}}
The bit I'm struggling with, is the MAGIC that happens as follows:
ClientResource cr = new ClientResource(….); // fine
IDataStruct resource = cr.wrap(IDataStruct.class); // <---- Magic here, but fine at Runtime.
if(cr.getResponse().getStatus().isSuccess()) // fine
{
PriceObject price = resource.retrieve();//<--- get to this line but then everything blows up because no converter is found. I can't use Jackson because GAE does not like it
}
The question is, what should the IDataStruct interface look like ??
Will.
Customer in the example is indeed a POJO. Depending on the converter you would use, you can make it serializable or not. BTW, Jackson should work on GAE, which issue did you encounter exactly?
IDataStruct should be a Java interface annotated with Restlet API annotations such as #Get, #Post, etc.
Regarding the user guide, you can find the edited version in GitHub, where I just fixed some of the broken links (will be published soon on Restlet.org):
https://github.com/restlet/restlet-sites/blob/master/modules/org.restlet/learn/guide/2.1/introduction/first-steps/first-client.md

"NotSupportedException" when WebRequest is unable to find a creator for that prefix

I have a really strange problem with WebRequest in a ServiceStack web application (hosted by XSP on Mono).
It seems that the registration of request modules works in a very strange way; I am using WebRequest to create an HTTP request, and it is failing because it was not able to find a creator for that "prefix" (HTTP).
The exception I am seeing is NotSupportedException, and I was able to track it to the fact that no creator is registered for the HTTP prefix (I am hitting https://github.com/mono/mono/blob/master/mcs/class/System/System.Net/WebRequest.cs, around line 479)
EDIT: more details: NotSupportedException is thrown by WebRequest.GetCreator, which uses the URL prefix as a key to choose which creator to return; in my case, a HttpRequestCreator. The exception is thrown because there is no creator registered for the "HTTP" prefix (actually, there are no creators at all).
So I searched around a little bit, dug into Mono sources, and found that modules are (or should be) added to the webRequestModules section of system.web in one of the various *.config files.
I looked at my machine.config file, and there it is:
System.Net.HttpRequestCreator, System, Version=4.0.0.0
Looking at WebRequest Mono sources
it seems that prefixes are added from configuration(s) inside the class static constructor (not a good choice, IMHO, but still.. it should work).
To test it, I tried to add an HttpRequestCreator to system.net/webRequestModules in my web.config; this is loaded by XSP/Mono and results in a duplicate key exception (which is expected since HttpRequestCreator should be already loaded, as it is already present in machine.config).
Even stranger: if I add a mock handler for Http, like this:
bool res = System.Net.WebRequest.RegisterPrefix ("http", new MyHttpRequestCreator ());
Debug.Assert (res == false);
The assertion sometimes pass... sometimes not!
(RegisterPrefix returns "false" if a creator for the same prefix is already registered; I expect it always to return false, but this is not the case! Again, it is completely random)
When the registration "fails" (i.e., returns false because an "HTTP" prefix is already registered), then the WebRequest can create requests for HTTP. It is as if calling RegisterPrefix "wakes up" the static constructor and let it run.
I am perplexed: it seems like a race condition in the execution of the static constructor of WebRequest, but this does not make sense (the runtime protects static constructors with a lock, IIRC)
What am I missing?
How could I solve or work around this problem?
Is it my fault (misunderstanding or missing something), or does it look like a Mono bug, so should I submit it?
Details:
mono --version
Mono JIT compiler version 3.0.6 (Debian 3.0.6+dfsg-1~exp1~pre1)
Possibly related, unanswered question:
HTTP protocol not supported in WebRequest under mono
Try this hacky workaround on this issue:
private static HttpWebRequest CreateWebRequest(Uri uri)
{
var type = Type.GetType("System.Net.HttpRequestCreator, System, Version=4.0.0.0,Culture=neutral, PublicKeyToken=b77a5c561934e089");
var creator = Activator.CreateInstance(type,nonPublic:true) as IWebRequestCreate;
return creator.Create(uri) as HttpWebRequest;
}
It sounds like you are experiencing a race condition in the execution of the static constructor of the WebRequest class. This could be caused by a variety of factors, including incorrect synchronization of access to shared resources, or the use of uninitialized variables.
One potential solution to this problem could be to ensure that the WebRequest class is initialized before attempting to use it. This can be done by accessing a static field or method of the WebRequest class before making any requests. For example:
int dummy = WebRequest.DefaultMaximumErrorResponseLength;
This will force the static constructor to run, ensuring that the WebRequest class is properly initialized before you attempt to make any requests.
Alternatively, you could try using the Lazy class to initialize the WebRequest class in a thread-safe manner. This can be done as follows:
private static readonly Lazy<int> DefaultMaximumErrorResponseLength =
new Lazy<int>(() => WebRequest.DefaultMaximumErrorResponseLength);
// ...
int dummy = DefaultMaximumErrorResponseLength.Value;
This will ensure that the WebRequest class is initialized in a thread-safe manner, without the risk of race conditions.

How to test flash.message in a Grails webflow?

I'm using webflows in Grails and I'm currently writing tests for it. Now, inside I've got something that throws an error so I set a message to the flash scope before redirecting:
...
if (some_condition) {
flash.message = "my error message"
return error()
}
...
Now, I know that when I'm going to display this in the GSP page, I access the flash message as
<g:if test="${message}">...
instead of the usual
<g:if test="${flash.message}">...
So anyway, I'm writing my test and I'm wondering how to test the content of the message? Usually, in normal actions in the controllers, I follow what's written in here . However, since this is a webflow, I can't seem to find the message even if I check controller.flash.message / controller.params.message / controller.message . I've also tried looking at the flow scope...
Any ideas on how to see the message then? Thanks a bunch!
Based on your example, you can access your flash.message as controller.request.message in your webflow test. I did a lot of googling for this same exact issue and a lot of webflow documentations talk about it merging all scopes into the "view model". But I also read somewhere that it merges the flash scope into the request scope for redirection. That's what prompted me to try looking in the controller.request in my test case.