I have some Rails 2.3.x code that I would like to run on Rails 3.0.3, but it seems to fail in my JSON to ActiveRecord code. Here is what I do:
mymodel = MyModel.new.from_json(json_string)
I get no errors here, but my object is empty as if there was no data in my json_string, but there is. If I look at the API (http://apidock.com/rails/ActiveRecord/Serialization/from_json) then it looks to me as it is not supported in 3.x, or?
I have tried with ActiveSupport::JSON.decode, but that decodes into a hashtable of key/values it seems?
Same problem here. The culprit is https://github.com/rails/rails/commit/c1d73270717f30498f8f4d55d6695509107c2834, here is an explanation: http://www.simonecarletti.com/blog/2010/04/inside-ruby-on-rails-serializing-ruby-objects-with-json/
The solution seems indeed to use
#obj.attributes = ActiveSupport::JSON.decode(json)
instead of "#obj.from_json(json)". At least for ActiveRecord objects, this works for me.
Related
I get this error because I have circular references defined in my object model. My question is, is there any way to resolve this using one of the following two options?
Using Newtonsoft.Json and options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
Using System.Text.Json and options.JsonSerializerOptions.ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.Preserve;
I'm not seeing a way to switch to Newtonsoft.Json in a Blazor WebAssembly application and I tried implementing option 2 in the ConfigureServices function of Startup.cs in my Server project but I still kept getting the error.
I'm just trying to find a solution that doesn't require me redefining my object model. The JsonIgnore attribute does not appear to be an option either because I assume, and it appears, that then any fields I define it on do not exist in the Json on the client which breaks my application.
Update: I found this site which looks to me like discusses exactly what I'm referring to here and how to implement the solution but I have not got it to work yet. If anyone is successfully using Blazor WebAssembly with circular references in your object model please let me know what you're doing.
https://github.com/dotnet/aspnetcore/issues/28286
Thank you for pointing out this error in Blazor. I found the answer in the issue you mentioned (this comment). You need to change json options also on the Client side. This works for me:
On server
services.AddControllersWithViews().AddJsonOptions(options =>
{
options.JsonSerializerOptions.ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.Preserve;
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});
On client
var response = await Http.GetFromJsonAsync<T>("{Address}", new JsonSerializerOptions
{
ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.Preserve,
PropertyNamingPolicy = null
});
To the two options you mentioned there is a third option available if you use .NET 6 or above.
Using System.Text.Json and options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
Beware that ignoring cycles have issues on its own (such as data corruption) but if you were depending on it when you were using Newtonsoft.Json then you will be fine as it is basically the same behavior.
If you prefer to go with ReferenceHandler.Preserve, please share more info on what error you are getting and I can try to help you out.
One way to go about this is specify how much depth an object is allowed to have. Please see the documentation here regarding how to do this with System.Text.Json. I think this may help.
Is there any way to implement ACL using Silex, but without Doctrine ORM?
Using entities we can handle this like this
$oidd = new Symfony\Component\Security\Acl\Domain\ObjectIdentity::fromDomainObject($message(\);
$acl = $app['security.acl.provider']->createAcl($oidd);
// the current user is the owner
$sid = Symfony\Component\Security\Acl\Domain\UserSecurityIdentity::fromAccount($currentUser);
$acl->insertObjectAce($sid, Symfony\Component\Security\Acl\Permission\MaskBuilder::MASK_OWNER);
Any solutions?
You might want to have a look at this example project.
https://github.com/davedevelopment/silex-acl-demo
The relevant bootstrap code is here (and works for me with Silex 1.2):
https://github.com/davedevelopment/silex-acl-demo/blob/master/app/bootstrap.php#L59
From the README:
This is a demo of Symfony's ACL using Silex. I've tried
to annotate the services in app/bootstrap.php, but to be honest, I
originally reverse engineered the symfony full stack frameworks DI
configuration without fully understanding what everything does, still
don't!
(Disclaimer: New to Rails here)
Say I have a Rails ActiveRecord Model that responds to "id":
User.first.id # => 22
My life has changed, and now I need to get this same object via JSON call, and I want minimal code changes.
I do this:
uri = URI.parse("http://localhost:3001/user/")
uri.query = "query=id#{user_id}"
#user = JSON.parse(open(uri).read)
I can now do:
#user["id"]
However, this is not good enough because it would mean too many changes.
Is there any way to turn this into a real User object? or something that will act like one in a simple one (I probably can create a dummy object with constructor, but I'm looking for something that will do it for me, and I suspect there is a simple Rails-way for it).
I have found a possible solution to this problem:
https://github.com/sprysoft/json_object
However, I realized I actually need the original ActiveRecord Model and not a dummy object..
That said, to my specific question, above gem is a possible solution.
A rails service I am currently working on requires that points are returned as a GeoJSON object within our json response. We are using rgeo and the mysql2spatial adapter to represent these points in our application and I would like to use the rgeo-geojson gem to handle the encoding if possible (we already use it to decode geojson on post).
I am currently overwriting as_json with the following code to achieve this:
def as_json(params)
l = {:lat_lng => ::RGeo::GeoJSON.encode(lat_lng)}
self.attributes.merge(l).as_json
end
However this is not optimal as the root (eg object: {}) is missing. Is there a function to easily include it? (a lot of our models have a lat_lng associated, so I'd rather not hard code it).
Any tips for a ruby/rails beginner would be greatly appreciated
For posterity, I fixed this in the "rgeo-activerecord" gem, version 0.3.4, after getting several reports on it. By default it renders spatial columns in WKT. To switch it to GeoJSON, set this:
RGeo::ActiveRecord::GeometryMixin.set_json_generator(:geojson)
The answer by NielsV will work sometimes but not every time. Specifically, it will work for geographic factories (i.e. geometry columns in PostGIS) but not for GEOS-backed factories.
You can specify it by including root with this line of code:
ActiveRecord::Base.include_root_in_json = true
I Hope this helps.
I solved this by extending the RGEO library with an as_json method for a Point, doing this it's no longer required to overwrite as_json in my own models. Thanks for your response though.
module RGeo
module Feature
module Point
def as_json(params)
::RGeo::GeoJSON.encode(self)
end
end
end
end
I started out looking at the JAX-RS plugin for grails and thought that was the way to go mainly because it was based on JSR-311 and I figure following standards is usually the smart thing to do. However, using Grail's UrlMappings it seems I basically achieve the same thing. I figure I'm missing something, however, we aren't doing anything overly complex. We basically just need to expose CRUD via an API. Example of doing the same thing with both versions:
JAX-RS:
#PUT
#Consumes(['application/json'])
#Produces(['application/json'])
Response putUser(User user) {
user.save(flush:true)
ok user
}
Grails:
def update = {
def user = new User(params['user'])
user.save(flush:true)
render user as JSON
}
Obviously, this is an overly-simplified example and like I said, maybe I'm missing something important. Also, the nice thing about the Grails built in mechanism is I can utilize Content Negotiation along with it.
Anyone have any opinions on this?
I had to make the same decision, and I found it just easier to use URL Mappings because the API was not that complex and there were a limited number of API calls that needed to supported.
If came down to what would be easier to maintain based on the LOE and the resources able to support the implementation.
The jax-rs plugin is very useful if you are creating web services straight to your domain models. It gives you a "generate-resource" command that automatically creates CRUD apis for your model.
grails generate-resource mydomain.Model
This part seems to work fine, however, I encountered quite a few bugs/problems with the plugin that I finally had to implement the REST services using URL-mappings.
Although the URL-mapping method seems to be more coding, it works perfectly.
import grails.converters.JSON
class ModelServiceController {
def id = params.id
def myModel = MyModel.findById(id)
render myModel as JSON
}
Here's the link for grails REST
http://grails.org/doc/1.0.x/guide/13.%20Web%20Services.html