This question already has an answer here:
What is the correct way to use JSON.NET to parse stream of JSON objects?
(1 answer)
Closed 5 years ago.
I have a file with multiple json objects.How can i read this in .net
I need the below string as two json obejcts
"{hello:'there'} {goodbye:'you',Thanks:'you'}"
#Anu: first of all, I do not think the string you specified "{hello:'there'} {goodbye:'you',Thanks:'you'}" is the proper Json string.
It should be like this one to deserialize properly
{"Arrival":{"Hello":"there"},"Departure":{"GoodBye":"you","Thanks":"you"}}.
Take a look at the example below for proper structure:
//You need to install the Json.Net and use it as shown below:
using Newtonsoft.Json;
//The object for Serializing and Deserializing:
public class Greeting
{
public Arrival Arrival { get; set; }
public Departure Departure { get; set; }
}
public class Arrival
{
public string Hello { get; set; }
}
public class Departure
{
public string GoodBye { get; set; }
public string Thanks { get; set; }
}
//Populate the Getting Object C# way
var greeting = new Greeting
{
Arrival = new Arrival { Hello = "there" },
Departure = new Departure { GoodBye = "you", Thanks = "you" }
};
//Serialize the C# object to Json
var jsonString = JsonConvert.SerializeObject(new
{
Arrival = new
{
greeting.Arrival.Hello
},
Departure = new { greeting.Departure.GoodBye, greeting.Departure.Thanks }
});
//Which produce this Json String: {"Arrival":{"Hello":"there"},"Departure":{"GoodBye":"you","Thanks":"you"}}
//Convert the Json string back to C# object - Deserialize the object
var greeting1 = (Greeting)JsonConvert.DeserializeObject(jsonString, typeof(Greeting));
Hope this helps and answered your question.
Good luck!
Dibu is right - your string is not a valid JSON object, so you can't deserialize it back to object(s) automatically.
You should either write your own parser (oops, don't do this) or force changing source input file to have one of:
Contain one valid JSON object (made of several separate objects), so you can deserialize it easily
Contain some separator(s) between individual objects, so you can split source string manually and deserialize objects one by one.
The best option is to change source file to contain one valid object, but I guess this was not your decision about such source file format...
There is a way. You need a JsonConverter to pass when you deserialize.
string json = #"{hello:'there'} {goodbye:'you',Thanks:'you'}";
IList<Greeting> greetings= new List<Greeting>();
JsonTextReader reader = new JsonTextReader(new StringReader(json));
// this is the important part, which makes the reader not throw exception
//when one json object is finished
reader.SupportMultipleContent = true;
while (true)
{
if (!reader.Read())
{
break;
}
JsonSerializer serializer = new JsonSerializer();
Greeting greeting= serializer.Deserialize<Greeting>(reader);
greetings.Add(greeting);
}
Related
I am trying to post objects to my server but the received objects have the value null.
Backend Code:
// Signature
public IActionResult Save(string num, string pat, string token, [FromBody]DataCl data, [FromBody]List<items> listItems)
// EDIT: Added class
public class Object
{
public List<items> listItems { get; set; }
public DataCl data { get; set; }
}
// So new signature
public IActionResult Save(string num, string pat, string token, [FromBody]Test test)
// The value is still null
Frontend Code:
post(num, data, list)
return this.http.post<any>(url,{data, list}, httpOptions).subscribe()
So the parameter num, pat and token are receiving the correct data but the data representing the body are not reciving any data - they are null.
With only one object it is working fine - the correct object was received but with two it does not work anymore but why? Is it something in the frontend code? Or backend?
Check the following article here
Don't apply [FromBody] to more than one parameter per action method.
The ASP.NET Core runtime delegates the responsibility of reading the
request stream to the input formatter. Once the request stream is
read, it's no longer available to be read again for binding other
[FromBody] parameters.
You cannot have two FromBody attributes. The from body is only read once.
{data, list} is one object anyway in javascript. There is no way to Post multiple objects in body, unless they are embedded.
{
object1: {}
object2: {}
}
And in you backend code:
class WrapperObjectResponse {
public Object1 = ...
public Object2 = ...
}
In your new signature, try this:
[Route("save/{num}/{pat}/{token}")]
public IActionResult Save(string num, string pat, string token, [FromBody]Test test)
And call like this:
return this.http.post<any>(url + '/' + num + '/' + pat + '/' + token + '/',{data: {}, list = []}, httpOptions).subscribe()
First, I create successfully web API in ASP.NET. API getting the XML from another server. I find the which suitable for XML all format change.
I tried to apply belove logic:
using (XmlReader reader = XmlReader.Create("XML.xml"))
{
//String starttime,Endtime;
while (reader.Read())
{
// Only detect start elements.
if (reader.IsStartElement())
{
switch (reader.Name)
{
case "EventInfo":
// Detect this element.
Console.WriteLine("Start <content> element. ");
Console.WriteLine();
break;
}
}
}
}
in this way only single file convert into another file.
I tried to create multiple files at a time convert into another format.
I gave the below format data from web API
It's a Normal XML Format Use:
<EventInfo>
<Event>
<EventId>1</EventId>
<EventName>shedule-1</EventName>
<EventText>ch1 Channel Description</EventText>
<StartTime>00:00:00</StartTime>
<Duration>00:30:00</Duration>
<Date>20.06.2019</Date>
</Event>
<EventInfo>
I apply the Logic in title tag its a starttime+duration is my end time and I Display EventName and Time both in tile tag.its all in dynamic.
Here Its ROKU format XML:
<Content>
//Here i only print the HH-MM.
<item title="00:00 - 00:30 shedule-1" LIVE="true" streamformat="mov" description="ch1 Channel Description" realeasedate="20.06.2019" description-color="0xC36419"/>
<Content>
Anyone know which is the best way to converting the XML. Thank you.
Please check out the below solution for your case:
1) Deserialize WebAPI Xml to C# object (say Events).
2) From (Events) C# object to required xml format using xml Linq.
Click here - For online execution
Step 1: Create a Class to deserailize the input xml structure.
public class Event
{
[XmlElement]
public string EventId { get; set; }
[XmlElement]
public string EventName { get; set; }
[XmlElement]
public string EventText { get; set; }
[XmlElement]
public string StartTime { get; set; }
[XmlElement]
public string Duration { get; set; }
[XmlElement]
public string Date { get; set; }
}
Step 2: Deserialize WebAPI Xml string to C# object and Reformat using xml linq.
string sXml = #"<EventInfo>
<Event>
<EventId>1</EventId>
<EventName>shedule-1</EventName>
<EventText>ch1 Channel Description</EventText>
<StartTime>00:00:00</StartTime>
<Duration>00:30:00</Duration>
<Date>20.06.2019</Date>
</Event>
</EventInfo>";
using (TextReader oReader = new StringReader(sXml))
{
// Deserialize Xml string to c# object
XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<Event>), new XmlRootAttribute("EventInfo"));
List<Event> lstEvents = (List<Event>)xmlSerializer.Deserialize(oReader);
if (lstEvents != null)
{
// Restructure the C# object to ROKU Xml Format using Xml Linq
XElement oResult = new XElement("Content", lstEvents.Select(t =>
new XElement("item",
new XAttribute("title", string.Format("{0} - {1} {2}", Convert.ToDateTime(t.StartTime).ToString("HH:mm"), Convert.ToDateTime(t.Duration).ToString("HH:mm"), t.EventName)),
new XAttribute("LIVE", "true"),
new XAttribute("streamformat", "mov"),
new XAttribute("description", t.EventName),
new XAttribute("realeasedate", t.Date),
new XAttribute("description-color", "0xC36419")
)));
// Saving the output as seperate xml file
oResult.Save("ROKU.xml");
}
else
{
Console.WriteLine("No Events Found");
}
}
}
We have a fun situation where we are storing json as a string in SQL Server. We don't not care what is in this object its pretty much a passthrough property. Passthrough meaning we just save it for clients and return it as is. We never read it in C#. I'm storing it as a nvarchar in the database but I'm trying to figure out how i can automagically serialize that string into a json object to return to the client. I dont want to have to in javascript call fromJson.
We are using Newtonsoft as our Json Serializer. Here is the highlevel setup:
DTO:
public class MyDto{
public dynamic SessionBag { get;set;}
}
Entity Framework Entity:
public class My{
public string SessionBag { get;set;}
}
A client would post/put us:
{"SessionBag":{"Name":"test"}}
We would then save it in the db as a string:
"{"Name":"test"}"
How can I serialize this so when it returns from Web.API it looks like:
{
SessionBag:{
Name: "test"
}
}
I'm currently messing around trying to get it to save using dynamic / object. But i can't figure how how to return it as a json object. I would love to figure out how to do this with just annotations.
Here is how I convert it to a string to save:
if (dto.SessionBag != null){
var serializer = JsonSerializer.Create(new JsonSerializerSettings(){
NullValueHandling = NullValueHandling.Ignore
});
using (var writer = new StringWriter()){
serializer.Serialize(writer, dto.SessionBag);
entity.SessionData = writer.ToString();
}
}
In case its helpful our WebApiControllers are pretty simple and just return an IHttpActionResult with the dto. All feedback is welcome.
So I think i figured it out. In my dto:
[JsonIgnore]
public string SessionBagString { get; set; }
public JObject SessionBag
{
get
{
if (!string.IsNullOrEmpty(SessionBagString))
{
return JObject.Parse(SessionBagString);
}
return null;
}
set
{
if(value != null)
{
SessionBagString = value.ToString();
}
}
}
In my repo code I now have:
if (dto.SessionBag != null)
{
entity.SessionBagString = dto.SessionBagString;
}
That pretty much worked for me. Let me know if there is a better way to do it.
I'm sending a request to server in the following form:
http://localhost:12345/api/controller/par1/par2
The request is correctly resolved to a method like:
[HttpPost]
public void object Post(string par1, string par2)
However, I pass additional data through the request content. How can I retrieve these data?
For the sake of example, let's say, that the request is sent from the form:
<form action="http://localhost:12345/api/controller/par1/par2" method="post">
<input type="hidden" name="data" value="value" />
<input type="submit" name="submit" value="Submit" />
</form>
From answer in this question:
How to get Json Post Values with asp.net webapi
Autoparse using parameter binding; note that the dynamic is made up of JToken, hence the .Value accessor.
public void Post([FromBody]dynamic value) {
var x = value.var1.Value; // JToken
}
Read just like Request.RequestUri.ParseQueryString()[key]
public async Task Post() {
dynamic obj = await Request.Content.ReadAsAsync<JObject>();
var y = obj.var1;
}
Same as #2, just not asynchronously (?) so you can use it in a helper method
private T GetPostParam<T>(string key) {
var p = Request.Content.ReadAsAsync<JObject>();
return (T)Convert.ChangeType(p.Result[key], typeof(T)); // example conversion, could be null...
}
Caveat -- expects media-type application/json in order to trigger JsonMediaTypeFormatter handling.
After spending a good bit of time today trying to wrap my brain around the (significant but powerful) paradigm shift between old ways of processing web form data and how it is done with WebAPI, I thought I'd add my 2 cents to this discussion.
What I wanted to do (which is pretty common for web form processing of a POST) is to be able to grab any of the form values I want, in any order. Say like you can do if you have your data in a System.Collections.Specialized.NameValueCollection. But turns out, in WebAPI, the data from a POST comes back at you as a stream. So you can't directly do that.
But there is a cool little class named FormDataCollection (in System.Net.Http.Formatting) and what it will let you do is iterate through your collection once.
So I wrote a simple utility method that will run through the FormDataCollection once and stick all the values into a NameValueCollection. Once this is done, you can jump all around the data to your hearts content.
So in my ApiController derived class, I have a post method like this:
public void Post(FormDataCollection formData)
{
NameValueCollection valueMap = WebAPIUtils.Convert(formData);
... my code that uses the data in the NameValueCollection
}
The Convert method in my static WebAPIUtils class looks like this:
/// <summary>
/// Copy the values contained in the given FormDataCollection into
/// a NameValueCollection instance.
/// </summary>
/// <param name="formDataCollection">The FormDataCollection instance. (required, but can be empty)</param>
/// <returns>The NameValueCollection. Never returned null, but may be empty.</returns>
public static NameValueCollection Convert(FormDataCollection formDataCollection)
{
Validate.IsNotNull("formDataCollection", formDataCollection);
IEnumerator<KeyValuePair<string, string>> pairs = formDataCollection.GetEnumerator();
NameValueCollection collection = new NameValueCollection();
while (pairs.MoveNext())
{
KeyValuePair<string, string> pair = pairs.Current;
collection.Add(pair.Key, pair.Value);
}
return collection;
}
Hope this helps!
I had a problem with sending a request with multiple parameters.
I've solved it by sending a class, with the old parameters as properties.
<form action="http://localhost:12345/api/controller/method" method="post">
<input type="hidden" name="name1" value="value1" />
<input type="hidden" name="name2" value="value2" />
<input type="submit" name="submit" value="Submit" />
</form>
Model class:
public class Model {
public string Name1 { get; set; }
public string Name2 { get; set; }
}
Controller:
public void method(Model m) {
string name = m.Name1;
}
It is hard to handle multiple parameters on the action directly. The better way to do it is to create a view model class. Then you have a single parameter but the parameter contains multiple data properties.
public class MyParameters
{
public string a { get; set; }
public string b { get; set; }
}
public MyController : ApiController
{
public HttpResponseMessage Get([FromUri] MyParameters parameters) { ... }
}
Then you go to:
http://localhost:12345/api/MyController?a=par1&b=par2
Reference: http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api
If you want to use "/par1/par2", you can register an asp routing rule. eg routeTemplate: "API/{controller}/{action}/{a}/{b}".
See http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api
Try this.
public string Post(FormDataCollection form) {
string par1 = form.Get("par1");
// ...
}
It works for me with webapi 2
None of the answers here worked for me. Using FormDataCollection in the post method seems like the right answer but something about my post request was causing webapi to choke. eventually I made it work by including no parameters in the method call and just manually parsing out the form parameters like this.
public HttpResponseMessage FileUpload() {
System.Web.HttpRequest httpRequest = System.Web.HttpContext.Current.Request;
System.Collections.Specialized.NameValueCollection formData = httpRequest.Form;
int ID = Convert.ToInt32(formData["ID"]);
etc
I found for my use case this was much more useful, hopefully it helps someone else that spent time on this answer applying it
public IDictionary<string, object> GetBodyPropsList()
{
var contentType = Request.Content.Headers.ContentType.MediaType;
var requestParams = Request.Content.ReadAsStringAsync().Result;
if (contentType == "application/json")
{
return Newtonsoft.Json.JsonConvert.DeserializeObject<IDictionary<string, object>>(requestParams);
}
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
Is there a way to handle form post data in a Web Api controller?
The normal approach in ASP.NET Web API is to represent the form as a model so the media type formatter deserializes it. Alternative is to define the actions's parameter as NameValueCollection:
public void Post(NameValueCollection formData)
{
var value = formData["key"];
}
ON WEB API.
[HttpGet]
[Route("api/Get_EXCUTA_PROCEDURE_IBESVNDACMVDD")]
public IHttpActionResult Get(int CodigoPuxada...)
{
string retornoErro = string.Empty;
try
{
//int codigoPuxada = entrada.CodigoPuxada;
SetKeyAtual(CodigoPuxada);
var repo = new ItemBroker_Dim_Canal_BookRepositorio(ConnectionString);
try
{
var dadosRetorno = repo.ExcuteProcedure_Busca_vbc_(CodigoPuxada,...); // method return object (dataset)
return Ok(dadosRetorno);
}
catch
{
throw;
}
}
catch (Exception ex)
{
retornoErro = ex.Message;
if (ex.InnerException != null)
retornoErro = ex.InnerException.ToString();
}
return Ok(retornoErro);
}
Other projet invoke web api...
(USING RESTSHARP DLL)
RestClient clientHttpPost1 = null;
string dadosVbc123 = string.empty;
clientHttpPost1 = new RestSharp.RestClient($"{urlWebApiAvante}Get_EXCUTA_PROCEDURE_IBESVNDACMVDD?CodigoPuxada=...");
RestSharp.RestRequest request2 = new RestSharp.RestRequest(RestSharp.Method.GET);
request2.RequestFormat = RestSharp.DataFormat.Json;
request2.AddHeader("Content-Type", "application/json;charset=utf-8");
string strAux1 = string.Empty;
request2.Timeout = 180000;
RestSharp.IRestResponse response = clientHttpPost1.Execute(request2);
if ((response != null) && response.StatusCode == System.Net.HttpStatusCode.OK)
{
try
{
var dataObjects = response.Content.ToString().Trim();
dadosVbc123 = dataObjects.ToString().Replace("\t", "");
if (dadosVbc123.Trim() == "{\"IBESVNDACMVDD\":[]}")
dadosVbc123 = string.Empty;
}
...
}
// converting JSON to dataset
string val1 = dadosVbc123.Replace("{\"IBESVNDACMVDD\":", "").Replace("}]}", "}]");
DataTable dtVBC123 = (DataTable)Newtonsoft.Json.JsonConvert.DeserializeObject(val1, (typeof(DataTable)));
In my application, I am sending a json object to a service and at the service end, I expect an object of type dynamic
public bool TestService(dynamic entity)
{
// process
}
When i debug and see the entity filled, I am not able to type cast it. Any idea how i can retrieve fields from the entity sent
I'm curious - if you're sending up a JSON formatted object, why not have your service method accept a string and then use something like JSON.net to cast it to the appropriate type?
public bool TestService(string entity)
{
var myObject = JsonConvert.DeserializeObject<MyObjectType>(entity);
//do stuff with myObject...
}
Or you could deserialize it into an anonymous object:
public bool TestService(string entity)
{
var myAnonymousObject = new { Name = String.Empty, Address = String.Empty };
var myObject = JsonConvert.DeserializeAnonymousType(entity, myAnonymousObject);
//do stuff with myObject
}
I guess I'm not sure why your JSON formatted object needs to be dynamic.