Alternatives to Dynamic JsonParsing - c#

I am using aws lambda's api request template to create and call post methods. I have to send a post body from my code, which should be json serialized.
Here is a way I am doing it now:
**dynamic pObj = new JObject();
pObj.Url = DownloadURL;
pObj.Name = IName;
pObj.ID = I.ID;**
Custom redirect = new Custom()
{
url = new Uri(lambdaEndpoint),
**Body = pObj.ToString(),**
Method = "POST",
Available = true
};
But I read an article where it talks about performance issues with using dynamic keyword.
Is there an alternative approach of doing this that is better in performance? Any help will be appreciated.
Thanks

An alternative to the usage of dynamic would be a direct deserialization. Since you know your object, it should fit as expected.
Demo
using System;
using Newtonsoft.Json;
public class Program
{
// create you class. You can generate it with http://json2csharp.com/ or use Visual Studio (edit>past special)
public class Custom
{
public string Url { get; set; }
public string Name { get; set; }
public string Id { get; set; }
}
public void Main()
{
string json = "{ \"Url\":\"xyz.com\", \"Name\":\"abc\", \"ID\":\"123\" }";
// the magic code is here! Go to http://www.newtonsoft.com/json for more information
Custom custom = JsonConvert.DeserializeObject<Custom>(json);
// custom is fill with your json!
Console.WriteLine(custom.Name);
}
}
output:
abc

Related

How can I add json data to a label in C#? ( windows forms )

so i want to get bitcoin price from a URL and see it in a label in my form.
URL
i tried to make a class for it with the code
public string price { get; set; }
but i don't know what to do after that, i searched a lot in google but they all show the result in list and etc
To deserialize, first you need to make a class with the attributes the JSON has. This page will help you a lot in that.
Once you have a class, you need to deserialize your JSON into that class. In C# I like to use JsonConvert from the library Newtonsoft.Json, you need to import it.
The method that deserializes it is JsonConvert.DeserializeObject.
One little example, let's say your class is called Bitcoin, then you would have to do it that way :
var myBitcoin = JsonConvert.DeserializeObject<Bitcoin>(yourJson);
EDIT: To pull your json from an URL you can use Webclient DownloadString method.
var myjson = new WebClient().DownloadString("url");
This post may also help you.
This should be your class.
public class APIResponse
{
public string symbol { get; set; }
public string price { get; set; }
}
Then in your function add these lines.
APIResponse response = new APIResponse();
response = JsonConvert.DeserializeObject<APIResponse>();
myPriceLabel.Text = response.price;
What did we do? We created a C# model same as the Json Data model and we took JSON data and converted it to APIResponse type so we can access it and use it as we like.
It can be achieved simply by converting the Json with generic object
var myBitcoin = JsonConvert.DeserializeObject<object>(yourJson);
thank you all for answering but i found the solution!
the code should be like this
string url = "https://api.binance.com/api/v3/ticker/price?symbol=BTCUSDT";
using (WebClient wc = new WebClient())
{
var json = wc.DownloadString(url);
JavaScriptSerializer oJS = new JavaScriptSerializer();
PriceClass obj = new PriceClass();
obj = oJS.Deserialize<PriceClass>(json);
BTCPrice_Label.Text = obj.price;
}
and the class should be like this
using System;
public class PriceClass
{
public string symbol { get; set; }
public string price { get; set; }
}

RavenDB 4.0 storing raw json

I'm using NLOG for logging with the JsonLayout and want to store these logs in RavenDB 4.0. Basically I'm trying to store raw json into ravendb using the RavenDB .NET client.
I had a working solution in RavenDB 3.5: using a class inheriting from "RavenJObject" but this functionality was depricated in 4.0.
I got it working by deserializing the json into a dynamic and storing the dynamic object. But this stores the document in a meaningless "JObjects" collection. It also seems overhead to convert json to dynamic and back to json again.
var obj = JsonConvert.DeserializeObject<dynamic>(jsonString);
session.Store(obj);
I know it's possible using the UI (raven studio). But i can't find a way doing it using the .Net client.
I think it's maybe possible using the http api, doing a post with the raw json. But I haven't found any documentation about this.
Who can help me out? Any advice is appreciated!
Here you have code sample which allows you to operate on generic type and assigns collection properly:
[Fact]
public void RawJson()
{
using (var store = GetDocumentStore())
{
using (var session = store.OpenSession())
{
var json = "{ 'Name' : 'John', '#metadata' : { '#collection': 'Users' } }";
var blittableJson = ParseJson(session.Advanced.Context, json);
var command = new PutDocumentCommand("users/1", null, blittableJson);
session.Advanced.RequestExecutor.Execute(command, session.Advanced.Context);
}
using (var session = store.OpenSession())
{
var user = session.Load<User>("users/1");
Assert.Equal("John", user.Name);
}
}
}
public BlittableJsonReaderObject ParseJson(JsonOperationContext context, string json)
{
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
{
return context.ReadForMemory(stream, "json");
}
}
public class User
{
public string Id { get; set; }
public string Name { get; set; }
}

Strange JSON Deserialization c#

I'm having troubles with some Deserialization because I'm not receiving an object like I'm used to but an array. Lets to the code, how I've being doing it:
JSON received:
[{"gcm_regID":"fsdf2156fw62f1wfwe512g"}]
Deserialization
var result = JsonConvert.DeserializeObject<Gcm>(response);
Handlers Tried:
public class Gcm
{
public List<Gcm_reg> gcm_regID { get; set; }
}
public class Gcm_reg
{
public string gcm_regID { get; set; }
}
I've tried just the Gcm_reg as well and nothing seems to work. How can I deserialize this? By the way, I'm using the newsoft JSON.
Best regards,
IEnumerable<Gcm_reg> result = JsonConvert.DeserializeObject<IEnumerable<Gcm_reg>>(response);
You can deserialize the object as an array or IEnumerable
Object should be like
public class Gcm
{
public string gcm_regID { get; set; }
}
So Try it
var result = JsonConvert.DeserializeObject<IEnumerable<Gcm>>(response);
You can directly generate classes from Json by using link
To create same type of object
var outputList = new List<Gcm>();
//loop through this part based on number of input
var itemToAdd = new Gcm();
itemToAdd .regID = 'something';
outputList.Add(itemToAdd );
and send outputList to server.

Hypermedia links with Servicestack new API

I am evaluating how to add hypermedia links to DTO responses. Although there is no standard, add List to the response DTOs seems to be the suggested approach.
Do you know of any example or reference of implementation using ServiceStack framework?
Adding List is ok for me, but my doubts are about where to put the logic of the following links (Within the service or a specialized class that holds the state machine?) and where to resolve the routes (A filter?)
Thanks.
[Update] From ServiceStack version v3.9.62 it is posible to access Routes configuration via EndpointHost.Config.Metadata.Routes.RestPath, so the solution provided by tgmdbm can be improved withouth the need of "IReturn + Routes attributes", just using Metadata.Routes information.
In fact all service metadata can be queried and used to cross-cutting concerns. Servicestack rocks.
The way I do this currently is I pass back a response dto which implements an interface
public interface IHaveLinks
{
[IgnoreDataMember]
IEnumerable<Link> Links { get; }
}
public class Link
{
public string Name { get; set; }
public IReturn Request { get; set; }
public string Method { get; set; }
}
Then I use a response filter to generate the urls and populate the response headers with the links.
this.ResponseFilters.Add((req, res, dto) =>
{
if (!(dto is IHaveLinks))
return;
var links = (dto as IHaveLinks).Links
if(links == null || !links.Any())
return;
var linksText = links
.Select(x => string.Format("<{0}>; rel={1}"), x.Request.ToUrl(x.Method), x.Name));
var linkHeader = string.Join(", ", linksText);
res.AddHeader("Link", linkHeader);
});
This seems the cleanest way. The Link object above effectively says "If you make this request with this method you will get back the named resource". The only HTTP thing that bleeds up to the BLL is Method. But you could get rid of that and only pass back GET urls. Or map it to some generalised "operation"?
As an example:
public class ExampleService : Service
{
public ExamplesResponse Get(ExamplesRequest request)
{
var page = request.Page;
var data = // get data;
return new ExamplesResponse
{
Examples = data,
Links = new []
{
new Link { Name = "next", Request = request.AddPage(1), Method = "GET" },
new Link { Name = "previous", Request = request.AddPage(-1), Method = "GET" },
}
}
}
}
[Route("/examples/{Page}")]
public class ExamplesRequest : IReturn<ExamplesResponse>
{
public int Page { get; set; }
// ...
}
(The AddPage method returns a clone of the request and sets the Page property appropriately.)
Hope that helps.

NancyFx binding a model to a dynamic type?

In Nancy, is there a way to bind the content of a POST request to a dynamic type?
For example:.
// sample POST data: { "Name": "TestName", "Value": "TestValue" }
// model class
public class MyClass {
public string Name { get; set; }
public string Value { get; set; }
}
// NancyFx POST url
Post["/apiurl"] = p => {
// this binding works just fine
var stronglyTypedModel = this.Bind<MyClass>();
// the following bindings do not work
// there are no 'Name' or 'Value' properties on the resulting object
dynamic dynamicModel1 = this.Bind();
var dynamicModel2 = this.Bind<dynamic>();
ExpandoObject dynamicModel3 = this.Bind();
var dynamicModel4 = this.Bind<ExpandoObject>();
}
Out of the box Nancy does not support dynamic model binding. TheCodeJunkie has written a quick ModelBinder to achieve that tho.
https://gist.github.com/thecodejunkie/5521941
Then you can use it like so
dynamic model = this.Bind<DynamicDictionary>();
As the previous answers point, there is no support for binding directly to a dynamic type, the most similar one is the ModelBinder provided by TheCodeJunkie in https://gist.github.com/thecodejunkie/5521941
However, this approach has a problem, and is that the DynamicDictionary resulting from this code does not serialize later properly, producing only the keys of the dictionary and losing the values. This is described here Why does storing a Nancy.DynamicDictionary in RavenDB only save the property-names and not the property-values? and as of today (version 1.4.3) is still happening, limiting seriously this approach.
The solution is to use a simple trick, accessing the raw data received in the POST and deserializing using JSON.Net. In your example it would be:
using System;
using System.Dynamic;
using Nancy;
using Nancy.Extensions;
using Newtonsoft.Json;
Post["/apiurl"] = p => {
dynamic obj = JsonConvert.DeserializeObject<ExpandoObject>(Request.Body.AsString());
//Now you can access the object using its properties
return Response.AsJson((object)new { a = obj.Prop1 });
}
Note that you need to use Nancy.Extensions for the Request.Body.AsString() call.
I was looking for a way to deserialize my POST body as dynamic and found this question, I’ll put my solution using Newtonsoft and extension method just in case that result useful for somebody else.
Extension method
using System.IO;
using Nancy;
using Newtonsoft.Json;
namespace NancyFx
{
public static class DynamicModelBinder
{
public static dynamic ToDynamic(this NancyContext context)
{
var serializer = new JsonSerializer();
using (var sr = new StreamReader(context.Request.Body))
{
using (var jsonTextReader = new JsonTextReader(sr))
{
return serializer.Deserialize(jsonTextReader);
}
}
}
}
}
Usage
using Nancy;
using Nancy.ModelBinding;
namespace NancyFx
{
public class HomeModule : NancyModule
{
public HomeModule(IAppConfiguration appConfig)
{
Post("/product", args => {
dynamic product = Context.ToDynamic();
string name = product.Name;
decimal price = product.Price;
return Response.AsJson(new {IsValid=true, Message= "Product added sucessfully", Data = new {name, price} });
});
}
}
}
I'm not sure, but you can try:
dynamic model = new ExpandoObject();
model = Request; //or Request.Form
return View["ViewName", model];
let me know if works :)

Categories

Resources