Don't understand how to use JSON.NET with ASP.NET Core WebAPI - json

I've completed my first ASP.NET Core Web API and I'd like to try my hand at manually serializing/deserializing JSON via the JSON.NET library. In the JSON.NET documentation they give the following simple manual serialization example:
public static string ToJson(this Person p)
{
StringWriter sw = new StringWriter();
JsonTextWriter writer = new JsonTextWriter(sw);
writer.WriteStartObject();
// "name" : "Jerry"
writer.WritePropertyName("name");
writer.WriteValue(p.Name);
// "likes": ["Comedy", "Superman"]
writer.WritePropertyName("likes");
writer.WriteStartArray();
foreach (string like in p.Likes)
{
writer.WriteValue(like);
}
writer.WriteEndArray();
writer.WriteEndObject();
return sw.ToString();
}
What's lacking for a beginner such as myself is how to use this string. For example, consider the following:
[HttpGet("/api/data")
[Produces("application/json")]
public IActionResult GetData()
{
return Ok(new Byte[SomeBigInt]);
}
In the above code I don't really know where ASP.NET Core serializes the array to JSON...I'm assuming it happens somewhere under the hood. If I were to manually serialize (using the JSON.NET example) some big Byte array, what do I do with the resultant string? Is it just "return Ok(myJsonString);"? Won't the built-in serializer - not knowing that it is already the result of a serialization operation- serialize it again?

Since Asp.Net Core is quite flexible, there are several ways to return JSON. If you want to return Json from a controller one of the most straight forward ways to do it is like this:
[HttpGet("/api/data")]
public JsonResult GetData() {
return Json(new {
fieldOneString = "some value",
fieldTwoInt= 2
});
}
Under the hood the Json() helper method on the Controlleris using JSON.NET to do the JSON serialization and then sending that as the response body.
You could do the same thing like this:
string jsonText = JsonConvert.SerializeObject(new {
fieldOneString = "some value",
fieldTwoInt= 2
});
Response.WriteAsync(jsonText);
Note: to use Response.WriteAsync(jsonText) you need to add using Microsoft.AspNetCore.Http to your file and have a project reference to Microsoft.AspNetCore.Http.Abstractions.

Related

How to force DotNetCore 2.1 Web API to output Json format? What library do I need?

I be straight to the point. I am in the process of converting ASP.Net web services into DotNetCore 2.1 services. My question is very simple. How do I get json output from a string (with a GET verb)?
I'm new at this, but almost every piece of documentation and recommendations do not work with DotNetCore.
Obviously, the following will not work:
[HttpGet]
public string Get()
{
return "{\"country_code\":\"US\",\"country_name\":\"United States\",\"region_name\":\"California\",\"city_name\":\"Los Angeles\",\"latitude\":\"34.052230\",\"longitude\":\" - 118.243680\",\"zip_code\":\"90001\",\"time_zone\":\" - 08:00\"}";
}
I just need to convert this string (or tell the client) that I want the output in json. The following does not work either - got a squiggly line under the "Json(" method and, for the life of me, can't find a reference to make it go away (I pulled it from an example, so they must be using a 3rd party json parsing library or there's a reference that I'm missing)
[HttpGet]
public JsonResult Get()
{
return Json("{\"country_code\":\"US\",\"country_name\":\"United States\",\"region_name\":\"California\",\"city_name\":\"Los Angeles\",\"latitude\":\"34.052230\",\"longitude\":\" - 118.243680\",\"zip_code\":\"90001\",\"time_zone\":\" - 08:00\"}", "application/json");
}
Ideally, I'd like to serialize an object to json, but figured I'd start with something ridiculously simple.
Anywho, if anyone can help.
If you don't already have a strongly typed model, you can build an anonymous type and return that from the controller
Simple Example.
public class MyController: Controller {
[HttpGet]
public IActionResult Get() {
var model = new {
country_code = "US",
country_name = "United States",
region_name = "California",
city_name = "Los Angeles",
latitude = 34.052230,
longitude = -118.243680,
zip_code = 90001,
time_zone = "- 08:00"
};
return Ok(model); //200 OK with content
}
}
In more complex scenarios you would get your objects from a data source.
No library needed, the framework out of the box will serialize the object(s) into JSON for you by default unless otherwise configured.
If you insist on passing a manually formatted string then use the ContemntResult object. Pass it the string and the content type.
[HttpGet]
public IActionResult Get() {
string json = "{\"country_code\":\"US\",\"country_name\":\"United States\",\"region_name\":\"California\",\"city_name\":\"Los Angeles\",\"latitude\":\"34.052230\",\"longitude\":\" - 118.243680\",\"zip_code\":\"90001\",\"time_zone\":\" - 08:00\"}";
return Content(json, new MediaTypeHeaderValue("application/json"));
}
Reference Format response data in ASP.NET Core Web API
Forcing a Particular Format
If you would like to restrict the response formats for a specific action you can apply the
[Produces] filter. The [Produces] filter specifies the response
formats for a specific action (or controller). Like most Filters, this
can be applied at the action, controller, or global scope.
[Produces("application/json")]
public class AuthorsController
The [Produces] filter will force all actions within the
AuthorsController to return JSON-formatted responses, even if other
formatters were configured for the application and the client provided
an Accept header requesting a different, available format.
Don't return string but object. So result of your actions are json string this is why you will get string in JSON and not an object
Make sure that your client is sending header "Content-Type": "application/json".
[HttpGet]
public Address Get()
{
return new Address{ CountryCode = "US"} ;
}

How to force a Web Api method to return date with a format like this: /Date(46546)/

I'm migrating an old application and I need that a specific web api 2 method returns date like this: /Date(46546)/ and not in the ISO 8601 format: 2016-10-31T07:22:57.1153868-05:00
My web api method looks like:
[Route("GetListData/{jtStartIndex:int=0}/{jtPageSize:int=0}/{jtSorting?}")]
[HttpPost]
public HttpResponseMessage GetListData(int jtStartIndex, int jtPageSize, string jtSorting)
{
try
{
var dataList = DataContainer.Instance.Data;
//HERE dataList is a collection of a custom model, a model that have properties of datetime type.
return this.Request.CreateResponse(HttpStatusCode.OK,
new { Result = "OK", Records = dataList, TotalRecordCount = dataList.Count });
}
catch (Exception ex)
{
return this.Request.CreateResponse(
HttpStatusCode.InternalServerError,
new { Result = "ERROR", Message = ex.Message });
}
}
As far as I know, newer WebAPI uses JSON.NET as the serializer by default, which adheres to the JSON standard and thus cannot serialize the format you requested, which is not JSON standard compliant.
Old WebAPI used Microsoft's own DataContractJsonSerializer, which only supports the non-standard-compliant format.
To get back to that serializer:
First, you have to add a serializer to your WebAPI project, at the end of the list of available serializers, which uses the old serializer library.
Then you you can select that very serializer for a certain controller.

Add JSON serializer to every model class?

When it comes to JSON encoding in Dart, per Seth Ladd's accouncement the finally approved now official way to go is dart:convert + JSON.Encode.
Let's say we have a bunch of model classes (PODOs) such as:
class Customer
{
int Id;
String Name;
}
Now, I'd love to be able to just JSON-encode my domain objects like this:
var customer = new Customer()
..Id = 17
..Name = "John";
var json = JSON.encode(customer);
Unfortunately, this won't work...
Uncaught Error: Converting object to an encodable object failed.
Stack Trace:
#0 _JsonStringifier.stringifyValue (dart:convert/json.dart:416)
#1 _JsonStringifier.stringify (dart:convert/json.dart:336)
#2 JsonEncoder.convert (dart:convert/json.dart:177)
....
... unless we explicitly tell dart:convert how to encode:
class Customer
{
int Id;
String Name;
Map toJson() {
Map map = new Map();
map["Id"] = Id;
map["Name"] = Name;
return map;
}
}
Do I really have to add a toJson method to every single one of my model classes, or is there a better way?
EDIT: this is the simple serialization I'm looking for:
{
"Id": 17,
"Name": "John"
}
Compare to ToJson in ServiceStack.Text, for instance.
Dart's serialization library (see Matt B's answer below) seems like a step in the right direction. However, this ...
var serialization = new Serialization()
..addRuleFor(Customer);
var json = JSON.encode(serialization.write(customer, format: new SimpleJsonFormat()));
... produces just an array with the values (no keys):
[17,"John"]
Using the default SimpleMapFormat on the other hand generates this complex representation.
Still haven't found what I'm looking for...
EDIT 2: Adding some context: I'm building a RESTful web service in Dart, and I'm looking for a JSON serialization which can easily be consumed by any client, not just another Dart client. For instance, querying the Stack Exchange API for this very question will create this JSON response. This is the serialization format I'm looking for. - Or, look at typical JSON responses returned by the Twitter REST API or the Facebook Graph API.
EDIT 3: I wrote a small blog post about this. See also the discussion on Hacker News.
IMO this is a major short-coming in Dart, surprising given its Web Application focus. I would've thought that having JSON support in the standard libraries would've meant that serializing classes to and from JSON would work like water, unfortunately the JSON support seems incomplete, where it appears the choices are to work with loosely typed maps or suffer through un-necessary boilerplate to configure your standard (PODO) classes to serialize as expected.
Without Reflection and Mirrors support
As popular Dart platforms like Flutter doesn't support Reflection/Mirrors your only option is to use a code-gen solution. The approach we've taken in ServiceStack's native support for Dart and Flutter lets you generate typed Dart models for all your ServiceStack Services from a remote URL, e.g:
$ npm install -g #servicestack/cli
$ dart-ref https://techstacks.io
Supported in .NET Core and any of .NET's popular hosting options.
The example above generates a Typed API for the .NET TechStacks project using the generated DTOs from techstacks.io/types/dart endpoint. This generates models following Dart's JsonCodec pattern where you can customize serialization for your Dart models by providing a fromJson named constructor and a toJson() instance method, here's an example of one of the generated DTOs:
class UserInfo implements IConvertible
{
String userName;
String avatarUrl;
int stacksCount;
UserInfo({this.userName,this.avatarUrl,this.stacksCount});
UserInfo.fromJson(Map<String, dynamic> json) { fromMap(json); }
fromMap(Map<String, dynamic> json) {
userName = json['userName'];
avatarUrl = json['avatarUrl'];
stacksCount = json['stacksCount'];
return this;
}
Map<String, dynamic> toJson() => {
'userName': userName,
'avatarUrl': avatarUrl,
'stacksCount': stacksCount
};
TypeContext context = _ctx;
}
With this model you can use Dart's built-in json:convert APIs to serialize and deserialize your model to JSON, e.g:
//Serialization
var dto = new UserInfo(userName:"foo",avatarUrl:profileUrl,stacksCount:10);
String jsonString = json.encode(dto);
//Deserialization
Map<String,dynamic> jsonObj = json.decode(jsonString);
var fromJson = new UserInfo.fromJson(jsonObj);
The benefit of this approach is that it works in all Dart platforms, including Flutter and AngularDart or Dart Web Apps with and without Dart 2’s Strong Mode.
The generated DTOs can also be used with servicestack's Dart package to enable an end to end typed solution which takes care JSON serialization into and out of your typed DTOs, e.g:
var client = new JsonServiceClient("https://www.techstacks.io");
var response = await client.get(new GetUserInfo(userName:"mythz"));
For more info see docs for ServiceStack's native Dart support.
Dart with Mirrors
If you're using Dart in a platform where Mirrors support is available I've found using a Mixin requires the least effort, e.g:
import 'dart:convert';
import 'dart:mirrors';
abstract class Serializable {
Map toJson() {
Map map = new Map();
InstanceMirror im = reflect(this);
ClassMirror cm = im.type;
var decls = cm.declarations.values.where((dm) => dm is VariableMirror);
decls.forEach((dm) {
var key = MirrorSystem.getName(dm.simpleName);
var val = im.getField(dm.simpleName).reflectee;
map[key] = val;
});
return map;
}
}
Which you can mixin with your PODO classes with:
class Customer extends Object with Serializable
{
int Id;
String Name;
}
Which you can now use with JSON.encode:
var c = new Customer()..Id = 1..Name = "Foo";
print(JSON.encode(c));
Result:
{"Id":1,"Name":"Foo"}
Note: see caveats with using Mirrors
I wrote the Exportable library to solve such things like converting to Map or JSON. Using it, the model declaration looks like:
import 'package:exportable/exportable.dart';
class Customer extends Object with Exportable {
#export int id;
#export String name;
}
And if you want to convert to JSON, you may:
String jsonString = customer.toJson();
Also, it's easy to initialize new object from a JSON string:
Customer customer = new Customer()..initFromJson(jsonString);
Or alternatively:
Customer customer = new Exportable(Customer, jsonString);
Please, see the README for more information.
An alternative is to use the Serialization package and add rules for your classes. The most basic form uses reflection to get the properties automatically.
Redstone mapper is the best serialization library I've used. JsonObject and Exportable have the downside that you have to extend some of their classes. With Redstone Mapper you can have structures like this
class News
{
#Field() String title;
#Field() String text;
#Field() List<FileDb> images;
#Field() String link;
}
It works with getters and setters, you can hide information by not annotating it with #Field(), you can rename field from/to json, have nested objects, it works on the server and client. It also integrates with the Redstone Server framework, where it has helpers to encode/decode to MongoDB.
The only other framework I've seen thats on the right direction is Dartson, but it still lack some features compared to Redstone Mapper.
I have solved with:
class Customer extends JsonObject
{
int Id;
String Name;
Address Addr;
}
class Address extends JsonObject{
String city;
String State;
String Street;
}
But my goal is bind data from/to json from/to model classes; This solution work if you can modify model classes, in a contrast you must use solution "external" to convert model classes;
see also: Parsing JSON list with JsonObject library in Dart
Another package solving this problem is built_value:
https://github.com/google/built_value.dart
With built_value your model classes look like this:
abstract class Account implements Built<Account, AccountBuilder> {
static Serializer<Account> get serializer => _$accountSerializer;
int get id;
String get name;
BuiltMap<String, JsonObject> get keyValues;
factory Account([updates(AccountBuilder b)]) = _$Account;
Account._();
}
Note that built_value isn't just about serialization -- it also provides operator==, hashCode, toString, and a builder class.
I have achieve with this:
To make this work, pass explicitToJson: true in the #JsonSerializable() annotation over the class declaration. The User class now looks as follows:
import 'address.dart';
import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart';
#JsonSerializable(explicitToJson: true)
class User {
String firstName;
Address address;
User(this.firstName, this.address);
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
You can check here: https://flutter.dev/docs/development/data-and-backend/json#generating-code-for-nested-classes
I prefer using https://ashamp.github.io/jsonToDartModel/ online tool write by myself.
It has features below:
online use, without plugin
support multidimensional list
support complex json
support convert all props to String type
empty props warning
single file
dart keyword protected
instant convert
I think it's better than other tools.Welcome if you have any suggestion, issue or bug report.
Some of the answers are no longer applicable to Flutter 2; here is the process for automatically creating toJson and fromJson methods:
https://flutter.dev/docs/development/data-and-backend/json#creating-model-classes-the-json_serializable-way
PS: I wish this would be as simple as using Newtonsoft library in Asp.Net, this solution is closest to an automated solution

Create JSON Request string using Javascript Overlay types in GWT

We have used JSO for our JSON parsing in GWT client side. Now, we need to convert our Java objects to JSON string. I just wanted to understand, how we can achieve this? JSO overlay types was used for JSON parsing. Can it also be used to create a JSON request string or do we have to go by some other means?
Generating a JSON object in JavaScript is pretty simple. You can do it like this:
var obj = { "var1": "hello", "var2": "world" };
this will generate a JSON object with two varibles ("var1" and "var2") with their values ("hello", "world").
The Object can be converted into a String (for sending purposes) with the JSON.stringify(jso); method.
Generating JSON data from the java code isn't possible (well not with a usefull result) since all varibles are optimzed to single Strings, so applying this method wouldn't hava a usefull result (if even possible).
If you have already a JSO object (generated with something like safeeval). You can edit your varibles there, like this:
public final native void newValue(String newValue) /*-{
this.ValueName = newValue;
}-*/;
If you then want the object as string you have to define the following method in your JSO class:
public final native String returnAsString () /*-{
return JSON.stringify(this);
}-*/;
or use this in you Java class: String s = (new JSONObject(jso)).toString();.
This way you can edit your original intput data and send the original object back to the server.
BR

Using arbitrary JSON objects in OpenRasta

I can't seem to find anything in the OpenRasta docs or tutorials that shows how to use arbitrary JSON objects (i.e. objects not predefined using C# classes) for both receiving from and responding back to the client.
One way to do it would be to use JsonValue and write a custom codec that would just use the (de)serialization features provided by JsonValue. That should be pretty straightforward and less than 50 lines of code, but I wondered if there isn't anything built into OpenRasta?
(One downside of JsonValue is that MS has not yet released it, so you can't yet deploy it to customers (see 1. "Additional Use Rights"). But in cases where that matters, any other Json library, like Json.NET can be used.)
I have written, like most people, a very simple codec that supports dynamics as inputs and outputs to handlers using json.net. You can also register that codec with an anonymous type and it works brilliantly. You end up with this:
public object Post(dynamic myCustomer) {
return new { response = myCustomer.Id };
}
I just implemented a JSON codec using JsonFx. It goes like this:
using System.IO;
using System.Text;
using JsonFx.Json;
namespace Example
{
[global::OpenRasta.Codecs.MediaType("application/json")]
public class JsonFXCodec : global::OpenRasta.Codecs.IMediaTypeWriter, global::OpenRasta.Codecs.IMediaTypeReader
{
public void WriteTo(object entity, global::OpenRasta.Web.IHttpEntity response, string[] codecParameters)
{
JsonWriter json = new JsonWriter();
using (TextWriter w = new StreamWriter(response.Stream, Encoding.UTF8))
{
json.Write(entity, w);
}
}
public object ReadFrom(global::OpenRasta.Web.IHttpEntity request, global::OpenRasta.TypeSystem.IType destinationType, string destinationName)
{
JsonReader json = new JsonReader();
using (TextReader r = new StreamReader(request.Stream, Encoding.UTF8))
{
return json.Read(r, destinationType.StaticType);
}
}
public object Configuration { get; set; }
}
}
If it is registered for "object" then it seems to work for any class:
ResourceSpace.Has.ResourcesOfType<object>()
.WithoutUri
.TranscodedBy<JsonFXCodec>();