I've a JsonResult object to return from a MVC method, but I need to remove one element from it before send it.
UPDATE:
I'm trying to do it without mapping it because the object is huge and very complex.
How can I achieve this?
For eg.:
public class MyClass {
public string PropertyToExpose {get; set;}
public string PropertyToNOTExpose {get; set;}
public string Otherthings {get; set;}
}
and
JsonResult result = new JsonResult();
result = Json(myObject, JsonRequestBehavior.AllowGet);
and then REMOVE PropertyToNOTExpose from the result.
UPDATE from real code:
public JsonResult GetTransaction(string id)
{
//FILL UP transaction Object
JsonResult resultado = new JsonResult();
if (CONDITION USER HAS NOT ROLE) {
var jObject = JObject.FromObject(transaction);
jObject.Remove("ValidatorTransactionId");
jObject.Remove("Validator");
jObject.Remove("WebSvcMethod");
resultado = Json(jObject, JsonRequestBehavior.AllowGet);
} else {
//etc.
}
return resultado;
}
You can create a new object, excluding the properties you don't want sent in the result...
var anonymousObj = new {
myObject.PropertyToExpose,
myObject.Otherthings
};
JsonResult result = Json(anonymousObj, JsonRequestBehavior.AllowGet);
Another options could be to convert the object to a Newtonsoft.Json.Linq.JObject and remove the property using JObject.Remove Method (String)
var jObject = JObject.FromObject(myObject);
jObject.Remove("PropertyToNOTExpose");
var json = jObject.ToString(); // Returns the indented JSON for this token.
var result = Content(json,"application/json");
You could try using the [ScriptIgnore] attribute on your property. This will cause the JavaScriptSerializer to ignore it. However, this means that it will be ignored on deserialization as well. I'm not sure whether that is an issue for your situation or not.
public class myClass
{
public string PropertyToExpose {get; set;}
[ScriptIgnore]
public string PropertyToNOTExpose {get; set;}
public string Otherthings {get; set;}
}
Related
My mehtod returns an empty list:
Here is my code:
[HttpGet]
[Route("GetDomoticzDevices")]
public async Task<List<DomoticzDeviceStatus>> GetAsync() {
KlevebrandContext dbContext = new KlevebrandContext();
List<DomoticzDeviceStatus> domoticzDeviceStatuses = new List<DomoticzDeviceStatus>();
foreach(var domoticzDevice in dbContext.TblDomoticzDevices.ToList())
{
var response = await client.GetAsync("http://10.0.0.11:8080/json.htm?type=devices&rid=" + domoticzDevice.Idx.ToString());
domoticzDeviceStatuses.Add(new DomoticzDeviceStatus(domoticzDevice, ((JObject)JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result))["result"][0]["Data"].ToString(), ((JObject)JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result))["result"][0]["LastUpdate"].ToString()));
}
return domoticzDeviceStatuses;
}
In my debugger the "domoticzDeviceStatuses" has 15 objects with set values, but in my browser it is empty.
Heres the result in the debugger:
There are porpper values in the list.
The DomoticzDeviceStatus class looks like this:
public class DomoticzDeviceStatus
{
TblDomoticzDevice _tblDomoticzDevice;
string _device_status;
string _timestamp;
public DomoticzDeviceStatus(TblDomoticzDevice tblDomoticzDevice, string device_status, string timestamp) {
_tblDomoticzDevice = tblDomoticzDevice;
_device_status = device_status;
_timestamp = timestamp;
}
}
If theres any more information you need just tell me :)
Thanks in advance!
Best regards Max
Try to change fields in your model to properties.
public class DomoticzDeviceStatus
{
public TblDomoticzDevice TblDomoticzDevice {get; set;}
public string Device_status {get; set;}
public string Timestamp {get; set;}
public DomoticzDeviceStatus(TblDomoticzDevice tblDomoticzDevice, string
device_status, string timestamp) {
TblDomoticzDevice = tblDomoticzDevice;
Device_status = device_status;
Timestamp = timestamp;
}
}
I am currently using .NET 6 and System.Text.Json for serialization. I am having issues where system.text.json does not deserialize the enum to string properly when I return the response using OkObjectResult or ObjectResult
I have used the following on model
public class Customer
{
public string? id { get; set; }
public string? Name { get; set; }
public string Address { get; set; }
[JsonConverter(typeof(JsonStringEnumConverter))]
public CustomerType Type {get; set;}
}
using System.Text.Json.Serialization;
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum CustomerType
{
NEW,
EXISTING
}
Now the API Code
public async Task<IActionResult> GetCustomerById(string Id)
{
var results = await _customerService.GetData(Id);
// The results have correct JSON data with enum as string but as soon as I pass this to OkObjectResult, it changes the enum back to int
return new OkObjectResult(results );
}
Service
public async Task<Customer> GetData(string Id)
{
var results = await _httpClient.SendAsync(Id); // Get Data
var jsonResults = await results.Content.ReadAsStringAsync();
var options = new JsonSerializerOptions{ Converters ={
new JsonStringEnumConverter()};
return JsonSerializer.Deserialize<Customer>(jsonResults ,
options ) ; // This returns the data correctly
}
Now my question why OkObjectResult breaks the code and return the integer instead of enum string value
You need to introduce the enum converter to ASP.NET in your startup code, like this:
services.AddJsonOptions(options =>
{
var converter = new JsonStringEnumConverter();
options.JsonSerializerOptions.Converters.Add(converter);
});
Here is the JSON response
{
"result": [
{
"sys_id": "85071a1347c12200e0ef563dbb9a71c1",
"number": "INC0020001",
"description": ""
}
]
}
Here is my JSON class
public class Result
{
public string sys_id { get; set; }
public string number { get; set; }
public string description { get; set; }
}
public class jsonResult
{
public IList<Result> result { get; set; }
}
Here is what I am doing to deserialize
strReponse = rClient.makeReqest();
Result deserializedProduct = JsonConvert.DeserializeObject<Result>(strReponse);
System.Windows.Forms.MessageBox.Show(deserializedProduct.number);
It looks like it never assigns anything into my JSON class.
This is my first time dealing with JSON and Web calls. What am i missing? The API call does return the correct JSON, and I used json2csharp to make my json class.
Thank you!
You need deserialize full object represented in json string. Which is jsonResult in your case.
After, you will get access to values, you need, through properties of jsonResult
strReponse = rClient.makeReqest();
var deserializedResult = JsonConvert.DeserializeObject<jsonResult>(strReponse);
var number = deserializedResult.result.First().number;
MessageBox.Show(number);
Because jsonResult.result is of type IList will be safer to loop through all possible results
strReponse = rClient.makeReqest();
var deserializedResult = JsonConvert.DeserializeObject<jsonResult>(strReponse);
foreach (var result in deserializedResult.result)
{
MessageBox.Show(result.number);
}
You should deserialize to jsonResult NOT Result.
So try this :
jsonResult deserializedProduct = JsonConvert.DeserializeObject<jsonResult>(strReponse);
Also you may get values of the list like this:
var firstResult = deserializedProduct.result.FirstOrDefault();
var someSpecialResults = deserializedProduct.result.Where(r=>r.number.Contains("123"));
Also :
if (firstResult != null)
System.Windows.Forms.MessageBox.Show(firstResult .number);
Also you may iterate them like this :
deserializedProduct.result.ForEach(r=> System.Windows.Forms.MessageBox.Show(r.number);)
I hope to be helpful for you:)
I'm using json.net to serialize my responses to the client
I'm building a controller action (in mvc) that produce a json string from types of objects
so it looks something like this:
string json = JsonConvert.SerializeObject(Activator.CreateInstance(type));
my problem is that when an object has an object inside of it (complex type), the activator assign null to it and then, the Json serializer doesn't serialize it at all
for example
if my object class looks like this:
public class Phone
{
public string Name {get; set;}
public Model Model {get; set;}
}
public class Model
{
public string Name {get; set;}
public string IMEI {get; set;}
}
the json string will be:
{"Name":null, "Model":null}
so is there a way to make be:
{"Name":null, "Model":{"Name":null, "IMEI":null}}
thank you all for your answers
OK
it took me some time to write this answer (stack overflow restriction) but i've found a great way to do it with reflection and recurssion I've created this method:
public void CreateFullInstance(object obj)
{
PropertyInfo[] properties = obj.GetType().GetProperties();
foreach(var property in properties)
{
Type propertyType = property.PropertyType;
if(!propertyType.IsPrimitive &&
propertyType.GetConstructor(Type.EmptyTypes) != null)
{
var val = Activator.CreateInstance(propertyType);
property.SetValue(obj,val);
CreateFullInstance(val);
}
}
}
when I call it, I just pass my initial:
var phone = Activator.CreateInstance(propertyType);
CreateFullInstance(phone);
var json = JsonConvert.SerializeObject(phone);
the downside for this method is that objects with no empty constructor will be ignored. I think I can fix that but then again as I said, these are POCO models so they all have empty constructors
You need to initialize Model in the constructor of Phone object.
public class Phone
{
public Phone()
{
Model = new Model();
}
public string Name {get; set;}
public Model Model {get; set;}
}
public class Model
{
public string Name {get; set;}
public string IMEI {get; set;}
}
You can also use the Activator.CreateInstance overload by which you can pass values as parameters to the constructor of a type.
Using Activator you are creating the object of main class that's why after serializing json string contain entries for properties of the class...{"Name":null, "Model":null}
Now if you want property names of Model class properties as well in the json string, then odo something because of which your inner class get initialized...
We can achieve it in two ways
1)In constructor of Phone class initialize Model class follows.
public class Phone
{
public Phone()
{
Model = new Model();
}
public string Name {get; set;}
public Model Model {get; set;}
}
2)
MyClassObject obj = (MyClassObject)Activator.CreateInstance(type);
obj.Model=new Model();
hope it helped
This is the JSON string -
"{\"body\":[\"VAL1\",\"VAL2\"],\"head\":{\"result\":true,\"time\":3.859}}"
These are my classes -
[Serializable]
public class ResponseHead
{
public bool result {get; set;}
public float time {get; set;}
}
[Serializable]
public class ResponseBody
{
public string[] body {get; set;}
}
[Serializable]
public class ResponseObj
{
public ResponseBody body {get; set;}
public ResponseHead head { get; set; }
}
And the code -
JavaScriptSerializer serializer = new JavaScriptSerializer();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
responseText = streamReader.ReadToEnd();
}
ResponseObj response_obj = new ResponseObj();
ResponseHead rhead = new ResponseHead();
rhead = serializer.Deserialize<ResponseHead>(responseText); //not working
The resultant ResponseHead object has values:
result: false
time: 0.0
It is not able to map the values correctly, but i'm not sure why. The ResponseBody values are coming in correctly.
Please help!
Looks like you are trying to read ResponseObj (which is top level object in your JSON), but coded for ResponseHead. Following should work:
var wholeObject = serializer.Deserialize<ResponseObj>(responseText);
rhead = wholeObject.head;