How set QuoteName settings in Json.Net? - json

First of all, I know that it's not valid JSON format, but it's my customer web service settings, I need to set QuoteName of Json.Net JsonTextWriter to be false, but I don't know how to do it properly. This is my try:
foreach (var c in a)
{
var jsonobjects = JsonConvert.SerializeObject(c, new JsonTextWriter
{
QuoteName = false
}
);
//Some code that using serialized json object
}
In order to clarify what I want. I need to have Json property name without quotes. Something like that: {Property: "Value"}.

Here is an example:
The class:
public class Address
{
public string Street { get; set; }
public uint Number { get; set; }
public string City { get; set; }
public string ZipCode { get; set; }
public string State { get; set; }
public string Country { get; set; }
}
Serialization logic:
var address = new Address
{
Street = "Fulton Street",
Number = 100,
City = "New York",
ZipCode = "10038",
State = "NY",
Country = "USA"
};
var serializer = new JsonSerializer();
var stringWriter = new StringWriter();
using (var writer = new JsonTextWriter(stringWriter))
{
writer.QuoteName = false;
serializer.Serialize(writer, address);
}
var json = stringWriter.ToString();
Console.WriteLine(json);
Output:
{
Street: "Fulton Street",
Number: 100,
City: "New York",
ZipCode: "10038",
State: "NY",
Country: "USA"
}
Example:
https://dotnetfiddle.net/zazT1T

Related

How to mock PATCH methods of WebAPI using MS Unit?

I have the following PATCH method for which I am writing Unit Tests.
[HttpPatch("{id}")]
public IActionResult Patch(Guid id, [FromBody] JsonPatchDocument<QuoteDraft> patch) {
Global.AccessToken = Request.Headers["Authorization"];
var draft = new QuoteDraft();
var json = string.Empty;
try {
draft = quoteDraftRepository.GetQuoteDraftById(id);
if (draft == null) {
throw new ArgumentException($"Draft quote not found for id {id}");
}
QuoteDraft quoteDraft = null;
foreach (var item in patch.Operations) {
json = Convert.ToString(item.value);
var lineItem = JsonConvert.DeserializeObject<LineItem>(json);
quoteDraft = AddLineItem(draft, lineItem);
}
return StatusCode(StatusCodes.Status200OK, new QuoteDraftResponse {
Message = messageHandler.GetMessage(MessageType.All),
QuoteDraft = quoteDraft
});
}
Below is my unit test method:
[testmethod]
public void patchtestmethod()
{
var jsonobject = new jsonpatchdocument<quotedraft>();
var quotedraft = new quotedraft
{
market = "noo",
program = "ils",
brochure = "2019",
season = "v1",
currency = "nok",
totalprice = 100,
};
var value = jsonconvert.serializeobject(quotedraft);
jsonobject.add("/lineitem/-", value);
quotecontroller.patch(it.isany<guid>(), jsonobject);
}
I am getting the error as shown in below screenshot:
Error Details
The json patch has to look something like this.
op: 'add',
path: '/lineItem/-',
value: {
destination: this.props.result.destination.code,
currency: this.props.result.currency.code,
sku: getSku(this.props.result.course.code, this.props.result.destination.code),
unitType: this.props.result.course.unitType,
startDate: format(this.props.result.startDate),
endDate: this.props.result.endDate,
quantity: this.props.result.numberOfWeeks.id,
category: 'Course',
language: 'NO',
departurePoint: this.props.result.departure ? this.props.result.departure.code : null,
description: this.props.result.course.description
},
Kindly let me know what I am missing.
Thanks
For jsonobject.Add, it accpets Expression<Func<TModel, TProp>> path which is used to define the path for this operation.
Model.cs
public class QuoteDraft
{
public string Market { get; set; }
public string Program
{
get; set;
}
public List<LineItem> LineItem { get; set; }
}
public class LineItem
{
public string Destination { get; set; }
public string Sku { get; set; }
}
Code
var jsonobject = new JsonPatchDocument<QuoteDraft>();
var quotedraft = new QuoteDraft
{
Market = "noo",
Program = "ils"
};
var lineItem = new LineItem
{
Destination = "D",
Sku = "S"
};
jsonobject.Add(q => q, quotedraft);
jsonobject.Add(q => q.LineItem, lineItem);
var value = JsonConvert.SerializeObject(jsonobject);

Insert JSON formatted string into JSON structure

I have a question about inserting a json formatted string into a json structure and having the final version be a combined JSON formatted string that can be serialized into a JSON structure. I am using the newtonsofts Json.NET
I have the following JSON structure:
public class ResponseJson
{
[JsonProperty(PropertyName = "header")]
public ResponseHeader responseHeader { get; set; }
[JsonProperty(PropertyName = "results")]
public string responseResults { get; set; }
}
public class ResponseHeader
{
[JsonProperty(PropertyName = "name")]
public string name { get; set; }
[JsonProperty(PropertyName = "version")]
public string version { get; set; }
}
In the code, I do the following:
ResponseJson responseJson = new ResponseJson();
responseJson.responseHeader = new ResponseHeader()
{
name = A_NAME,
version = A_VERSION
};
responseJson.responseResults = resultJson;
return JsonConvert.SerializeObject(responseJson, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
resultJson is a properly formatted JSON string (in this case, an array of objects, but could be anything JSON formatted). Right now, if i execute the code, I get the following (which is expected, since "results" is declared as a string):
{
"header":
{
"name":"abcd",
"version":"1.0"
},
"results":
"[{\"data\":{\"level\":\"100\"},\"code\":{\"value\":\"JBC\",\"type\":\"ev\"},\"time\":{\"start\":\"20\",\"end\":\"101\"}}]"
}
what I do need as an output is:
{
"header":
{
"name":"abcd",
"version":"1.0"
},
"results":
[
{
"data":
{
"level":"100"
},
"code":
{
"value":"JBC",
"type":"ev"
},
"time":
{
"start":"20",
"end":"101"
}
}
]
}
While you don't explain how you create your resultJson variable, it's implied from your code that you are double-serializing your results: you compute an array of "result" classes, serialize them to a JSON string, store the string in your ResponseJson class, and them serialize that in turn. The embedded JSON string then gets escaped as per the JSON standard, which is what you are seeing.
You need to avoid double-serializing your data, for instance by using the following data model:
public class ResponseJson<T>
{
[JsonProperty(PropertyName = "header")]
public ResponseHeader responseHeader { get; set; }
[JsonProperty(PropertyName = "results")]
public T responseResults { get; set; }
}
public static class ResponseJson
{
public static ResponseJson<T> Create<T>(T responseResults, ResponseHeader responseHeader)
{
return new ResponseJson<T> { responseResults = responseResults, responseHeader = responseHeader };
}
}
public class ResponseHeader
{
[JsonProperty(PropertyName = "name")]
public string name { get; set; }
[JsonProperty(PropertyName = "version")]
public string version { get; set; }
}
Then you would do:
var results = GetResults(); // Get your result data
var responseJson = ResponseJson.Create(results, new ResponseHeader()
{
name = A_NAME,
version = A_VERSION
});
return JsonConvert.SerializeObject(responseJson, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
If for whatever reason you must embed a previously serialized JSON string as JSON rather than as a string literal, you'll need to re-parse it back to a JToken:
string resultJson = GetResultJson(); // Get result json string.
var responseJson = ResponseJson.Create(JToken.Parse(resultJson), new ResponseHeader()
{
name = A_NAME,
version = A_VERSION
});
return JsonConvert.SerializeObject(responseJson, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
Json.NET will include the JToken in your outer JSON as nested JSON rather than as a string literal.

ASP.NET Web Api: Correct way to serve OData-queryable GET requests

What is the right way to serve OData-queryable GET requests in ASP.NET Web Api? That may sound like a "what is better" question, but it should be a "what does work" question.
Some assumptions:
To enable OData-querying, you have to put the Queryable attribute to the action method that returns IQueryable<Model>. Therefore, you have to expose the domain model?
The domain model uses Entity Framework 5 and has navigation properties. The XML and Json Serializers do not like the EF proxies, so you have to disable them for OData queries?
The serializers pick up the navigation properties and serve them to the user.
So if I have a Category type that has navigation properties for parent and children, the serializers complain that I have cyclic references, and I cannot get rid of this error.
I have read that I should use DTOs, but HOW? How can I provide a IQueryable<DTOModel> to the user that will create the appropriate SQL for the database? Remember, I want to use $filter and the like.
I just want to give the user a filterable list of Model objects without the serialized navigation properties.... but HOW?
You don't have to expose IQueryable<> - you can create a method that accepts an instance of ODataQueryOptions and process this yourself. Here's a code sample that does most of what you require. It should be more than enough for you to work out the solution that works best for you. This method will also allow you to keep your EF proxy classes.
using System.Web.Http.OData;
using System.Web.Http.OData.Builder;
using System.Web.Http.OData.Query;
[ActionName("Dto")]
public IList<DtoModel> GetDto(ODataQueryOptions<DtoModel> queryOptions)
{
var data2 = DatabaseData();
//Create a set of ODataQueryOptions for the internal class
ODataModelBuilder modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Model>("Model");
var queryContext = new ODataQueryContext(
modelBuilder.GetEdmModel(), typeof(Model));
var newQueryOptions = new ODataQueryOptions<Model>(queryContext, Request);
var t = new ODataValidationSettings() { MaxTop = 25 };
var s = new ODataQuerySettings() { PageSize = 25 };
newQueryOptions.Validate(t);
IEnumerable<Model> results =
(IEnumerable<Model>)newQueryOptions.ApplyTo(data2, s);
int skip = newQueryOptions.Skip == null ? 0 : newQueryOptions.Skip.Value;
int take = newQueryOptions.Top == null ? 25 : newQueryOptions.Top.Value;
IList<Model> internalResults = results.Skip(skip).Take(take).ToList();
// map from Model to Dto here using AutoMapper
AutoMapper.Mapper.CreateMap<Model, DtoModel>();
IList<DtoModel> webResults =
AutoMapper.Mapper.Map<IList<Model>, IList<DtoModel>>(internalResults);
return webResults;
}
The data used in the example is a simple Queryable set of data:
private IQueryable<Model> DatabaseData()
{
return (
new Model[] {
new Model() { id = 1, name = "one", type = "a" },
new Model() { id = 2, name = "two", type = "b" },
new Model() { id = 3, name = "three", type = "c" },
new Model() { id = 4, name = "four", type = "d" },
new Model() { id = 5, name = "five", type = "e" },
new Model() { id = 6, name = "six", type = "f" },
new Model() { id = 7, name = "seven", type = "g" },
new Model() { id = 8, name = "eight", type = "h" },
new Model() { id = 9, name = "nine", type = "i" }
})
.AsQueryable();
}
These are the test classes:
public class Poco
{
public int id { get; set; }
public string name { get; set; }
public string type { get; set; }
}
public class DtoModel
{
public int id { get; set; }
public string name { get; set; }
public string type { get; set; }
}
public class Model
{
public int id { get; set; }
public string name { get; set; }
public string type { get; set; }
public virtual ICollection<Poco> Pocos { get; set; }
}

Is there a way to ignore default values during serialization with ServiceStack json?

I am using Entity Framework as my ORM. It has ComplexTypeAttribute (which is used to annotate POCO's). Properties that are complex types, are always instantiated (using default constructor), regardless of their value; And as a consequence, are always serialized by ServiceStack JsonSerializer (along with their properties).
JSON.NET has an enum called DefaultValueHandling, which can be used in these situations.
Does ServiceStack have something similar?
For example:
class Person
{
string Name { get; set; }
Address Address { get; set; }
}
[ComplexType]
class Address
{
string Street { get; set; }
int Number { get; set; }
int PostalCode { get; set; }
}
When I serialize a person that doesn't have address I get this:
"{ Name: Jim, Address : { Number: 0, PostalCode: 0 } }"
In Json.Net if I set DefaultValueHandling to Ignore, I only get
"{ Name: Jim }"
Yes, here are the different ways you can ignore properties with ServiceStack's JSON and Text serializers.
The serializers also support multiple hooks to customize serialization and deserialization.
The JsConfig class shows all the customizations that are possible.
Please consider changing your value types to nullable data types and set null as default value for any reference type.
class Person
{
string Name { get; set; }
Address Address { get; set; }
}
[ComplexType]
class Address
{
string Street { get; set; }
int? Number { get; set; }
int? PostalCode { get; set; }
}
This should help you get rid of attributes with default values as ServiceStack Text will omit properties with null value. Also observe that 'Age' which is of type int? is omitted from serialized output when it is null. The example also demonstrates serialization using anonymous objects.
Example below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ServiceStack;
namespace JsonTest
{
class Person
{
public string Name { get; set; }
public string Address { get; set; }
public int? Age { get; set; }
public List<Person> Children { get; set; }
public Person()
{
Children = new List<Person>();
}
}
class Program
{
static void Main(string[] args)
{
var c1 = new Person { Name = "John", Address = "USA", Age = null };
var c2 = new Person { Name = "John", Address = "USA", Age = 12 };
List<Person> children = new List<Person>();
children.Add(c1);
string name = "Jim";
// Uncomment lines below and check - Children attribute is omitted from JSON result
// children = null;
// name = null;
var p1 = new { Name = name, Address = "USA", Age=40, Children = children};
var p2 = new Person { Name = "Jim", Address = "USA" , Age = null};
p2.Children.Add(c2);
Console.WriteLine(p1.ToJson());
Console.WriteLine(p2.ToJson());
Console.ReadLine();
}
}
}
Output:
{"Name":"Jim","Address":"USA","Age":40,"Children":[{"Name":"John","Address":"USA","Children":[]}]}
{"Name":"Jim","Address":"USA","Children":[{"Name":"John","Address":"USA","Age":12,"Children":[]}]}
{"Address":"USA","Age":40}
{"Name":"Jim","Address":"USA","Children":[{"Name":"John","Address":"USA","Age":12,"Children":[]}]}

how to pass Json array in string - webapi in asp

I am using post method in that method i want to pass entire Json in string like this way
{Data:" JsonArray"} in Jssonarray I want to pass this value
{ "version" : 2,
"query" : "Companies, CA",
"begin" : 1,
"end" : 3,
"totalResults" : 718,
"pageNumber" : 0,
"results" : [
{ "company" : "ABC Company Inc.", "city" : "Sacramento", "state" : "CA" } ,
{ "company" : "XYZ Company Inc.", "city" : "San Francisco", "state" : "CA" } ,
{ "company" : "KLM Company Inc.", "city" : "Los Angeles", "state" : "CA" }
]
}
When i pass this I am getting 500 internal Error
Please help me how to pass Entire Json in a single string.
One way is to navigate to http://json2csharp.com/, paste your Json and hit "GO".
The result will be this one (I fixed the capitalization):
public class Result {
public string Company { get; set; }
public string City { get; set; }
public string State { get; set; }
}
public class RootObject {
public int Version { get; set; }
public string Query { get; set; }
public int Begin { get; set; }
public int End { get; set; }
public int TotalResults { get; set; }
public int PageNumber { get; set; }
public Result[] Results { get; set; }
}
Paste this into your application.
Your POST-Method then could look like this:
[WebInvoke(Method = "POST", UriTemplate = "")]
public HttpResponseMessage Add(RootObject root) {
// do something with your root objects or its child objects...
return new HttpResponseMessage(HttpStatusCode.Created);
}
And you're done with this method.
Another method is to use the new JsonValue and JsonArray introduced with Web API whereas you don't need RootObject and Result.
Just use your POST-Method:
[WebInvoke(Method = "POST", UriTemplate = "")]
public HttpResponseMessage Add(JsonValue json) {
JsonArray arr = (JsonArray) json["results"];
JsonValue result1 = arr[0];
var company = result1["company"]; // results in "ABC Company Inc."
return new HttpResponseMessage(HttpStatusCode.Created);
}
You should get a clue...
You can prettify the whole thing:
[WebInvoke(Method = "POST", UriTemplate = "")]
public HttpResponseMessage Add(JsonValue json) {
var arr = json["results"];
var result1 = arr[0];
var company = result1["company"]; // results in "ABC Company Inc."
return new HttpResponseMessage(HttpStatusCode.Created);
}