Is it possible to serialize a classname similar to a property - asp.net-core

I understand I can use code similar to the below to change the property name from Name to name when it is serialized but I also want to change the object name when it is serialized and returned using return something like Ok(myobj);
But, is it possible to do something similar for the class as below so it is serialized as person and not Person. I've looked at JsonObject but can't see anything on there.
[JsonObject(PropertyName="person")]
public class Person
{
[JsonProperty(PropertyName = "name")]
public String Name { get; set; }
}

If you just want your class name to start with a lowercase letter, you can do this:
[JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))]
public class Person
{
}
This would set the first letter of your class name to lowercase since it uses CamelCaseNamingStategy, you can also create your own custom naming strategy to fit your needs, implementation of existing naming stategies can be found here: (https://github.com/JamesNK/Newtonsoft.Json/tree/master/Src/Newtonsoft.Json/Serialization)

You will need another wrapper object to have like that. You can use:
return Ok(new{
Person = myobj
});

Related

How to support C# dynamic types in an gRPC proto file

We have a POST action in our asp.net core application that accepts a dynamic object.
[HttpPost]
public Task<ActionResult> SubmitAsync(dynamic unitOfWork)
We'd like to transform this POST action to a gRPC server and we'd like to continue receiving dynamic objects in the gRPC service. What is the equivalent of C# dynamic definition in gRPC protobuf file definition? Or if that cannot be achieved what's the best way to receive a dynamic object?
That isn't really a thing right now. In protobuf terms, Any is the closest thing, but I have not yet implemented that in protobuf-net (it is on my short term additions list). The legacy "dynamic types" feature in protobuf-net (that sends type metadata) is actively being phased out, with Any being the preferred route since it allows cross-platform usage and doesn't have the same metadata dependencies.
Frankly, though, I'd probably say "just don't do this"; instead, prefer oneof; it isn't likely that you actually mean "anything" - you probably just mean "one of these things that I expect, but I don't know which", and oneof expresses that intent. More: protobuf-net implements inheritance via oneof, so a good option is something like:
[ProtoContract]
[ProtoInclude(1, typeof(FooRequest))]
[ProtoInclude(2, typeof(BarRequest))]
public abstract class RequestBase {}
[ProtoContract]
public class FooRequest {}
[ProtoContract]
public class BarRequest {}
You can pass messages with fields whose type was not known in advance. You can also pass messages with fields that are not typed, such as dynamic objects that can take any scalar values, and collections null values are allowed.
To do so, import the proto file "google/protobuf/struct.proto" and declare the
dynamic type as google.protobuf.Value.
So, first add bellow line at the top of your proto file:
import "google/protobuf/struct.proto";
Here my sample message with two dynamic fields:
message BranchResponse {
google.protobuf.Value BranchId = 1;
google.protobuf.Value BranchLevel = 2;
}
Note that: the generated type in C# is Value and belongs to the Google.Protobuf.WellKnownTypes namespace, which belongs itself to the Google.Protobuf assembly. This type inherits from the IMessage, IMessage, IEquatable, IDeepCloneable, and IBufferMessage interfaces that all belong to the Google.Protobuf assembly, except for IEquatable, which comes from the .NET System.Runtime assembly. To write and read dynamic values, we have a set of methods available that shown bellow: (these are write static functions)
We can fill BranchResponse model like this:
var branch = new BranchResponse();
branch.BranchId = Value.ForNumber(1);
branch.BranchLevel = Value.ForStruct(new Struct
{
Fields = {
["LevelId"] = Value.ForNumber(1),
["LevelName"] = Value.ForString("Gold"),
["IsProfessional"] = Value.ForBool(true)}
});
The read Value type is straightforward. The Value type has a set of properties that exposes its value in the wanted type. (these are read static functions)
At the end, you need to read data from your response model like this:
Here my c# classes that my response model is supposed to bind to them.
public class BranchModel
{
public int BranchId { get; set; }
public LevelModel Level { get; set; }
}
public class LevelModel
{
public int LevelId{ get; set; }
public string LevelName{ get; set; }
public bool IsProfessional { get; set; }
}
Finally:
var branch = new BranchResponse(); // Received filled from a gRPC call
// Read
var branchModel = new BranchModel
{
BranchId = Convert.ToInt32(branch.BranchId.NumberValue),
Level= new LevelModel
{
LevelId = Convert.ToInt32(branchModel.Level.StructValue.
Fields["LevelId"].NumberValue),
LevelName = branchModel.Level.StructValue.
Fields["LevelName"].StringValue,
IsProfessional = branchModel.Level.StructValue.
Fields["IsProfessional"].BoolValue,
}
};

How to match a class with annotation inside?

I have an annotation named Metric
#Target({ElementType.FIELD, ElementType.METHOD})
public #interface Metric {
String name() default "";
}
I want to weave some logic when some methods with the #Metric annotation, like:
public class MethodWithMetricDemo{
#Metric
public void targetMethod(){
// do some thing
}
}
But how to match the class MethodWithMetricDemo in new AgentBuilder.Default().type(xxxxxxxxxxxxxxxx) ?
You would need to match your type based on the method annotatation. As methods are inherited virtually, you would however need to travers the entire class hierarchy by hasSuperType(declaresMethod(isAnnotatedWith(...))). This is possible but rather expensive. If you choose to use such a matcher, you should probably restrict your matching to a given namespace.

Providing Jackson Mapper multiple ways to deserialize the same object

I'm trying to deserialize two types of json:
{
name: "bob",
worksAt: {
name: "Bobs department store",
location: "downtown"
},
age: 46
}
and
{
name: "Tom",
worksAt: "company:Bobs department store",
age: 27
}
into these objects:
The first way creates two new objects, the second way requests the object from the database based on the contents of a string.
sort of like how jackson mapper can deserialize an arbitrary string into an object, for objects like this:
public class Company{
public String name;
public Employee[] employees
public Company(){}
public Company(String json){
//turn string into object using whatever encoding you want blah blah blah...
}
}
The trouble is I need both. I need it to handle objects and strings. Both could arrive from the same input.
The first think I tried was making a Converter
It says these create a delegate type to pass to the deserializer, but the converter is always applied even when the datatype isn't a string. So that didn't work.
I've also tried a normal deserializer, but I can't find a way to defer to the BeanDeserializer. The beanDeserializer is so complicated that I can't manually instantiate it. I also see no way to defer to a default deserializer in jackson mapper.
Do I have to re-implement jackson mappers deserialization to do this? Is there any way for a deserializer to say "I can't do this, use the default implementation."?
Edit: Some further progress. Based on the Jackson Mapper source code, it looks like you can instatiate bean deserializers like this:
DeserializationConfig config = ctxt.getConfig();
JavaType type = config.constructType(_valueClass);
BeanDescription introspect = config.introspect(type);
JsonDeserializer<Object> beanDeserializer = ctxt.getFactory().createBeanDeserializer(ctxt, type , introspect);
but for some reason all the _beanProperties have the FailingDeserializer set for their _valueDeserializer and the whole thing fails. So I have no idea why that happens...
Have you tried writing a custom deserializer? This gives you the most control on how Jackson deserializes the object. You may be able to try to deserialize one way, and if there's an error, try another way.
Jackson can also handle polymorphic deserialization, though this would require a small change to the json to include type information, and it sounds like your problem constraints might not allow that.
If I understand the problem correctly, I would recommend using JsonNode. You can define a setter in your top-level type like this:
setWorksAt(JsonNode node) {
if (node.getNodeType == JsonNodeType.STRING) {
String name = node.getText();
name = name.substring(name.lastIndexOf(':'));
this.company = new Company(name);
} else if (node.getNodeType == JsonNodeType.OBJECT) {
this.company = mapper.treeToValue(node, Company.class);
}
}
That allows you to handle the two separate worksFor inputs, while still allowing the standard mapper to handle any substructures for the OBJECT case.
With recent versions of Jackson (2.8+ I think, definitely works with 2.9) you can use multiple #JsonCreator and do something like this:
public class Company {
private String name;
private String location;
private Company(String name, String location) {
this.name = name;
this.location = location;
}
private Company(String stringRepresentation) {
// add code here to parse string and extract name and location
}
#JsonCreator
private static Company fromJson(
#JsonProperty("name") String name,
#JsonProperty("location") String location)
{
return new Company(name, location);
}
#JsonCreator
private static Company fromJson(String str) {
return Company(str);
}
}

Pattern name/Convention -> Class that merge different attributes from other classes

I wanted to know if there is a known pattern or convention for the following scenario:
I have two classes: MAT (name:String, address:String) & MATversion(type:String, version:int)
Now I have a DataGrid (DataTable) which will take a generic List of objects for the column mapping and data filling.
The columns should be name, type, version. (Which are distributed in MAT and MATversion)
So I create a class to make this work. This class will merge the needed properties from each class (MAT, MATversion).
-> MAT_MATversion (name:String, type:String, version:int).
Does there exist a naming convention for such an class like MAT_MATversion? Any pattern that mirrors that?
Thanks!
Is there any specific reason why the merged result has to be a unique class?
I'm assuming every MAT object has a single MATversion
you can add a couple of custom properties who will return the type and version of the underlying MATversion object
In C# this would result in something like this
public class MAT{
public String name{ get;set;};
public String adress{ get;set;};
public MATversion myVersion;
public String type {
get{
return myVersion.type;
}
set{
myVersion.type = value;
}
}
public int version {
get{
return myVersion.version;
}
set{
myVersion.version = value;
}
}
}
I'm aware that this doesn't answer the question about design patterns, but I couldn't ask/suggest another approach in a comment since I don't have that right yet.

WCF, Linq Error:cannot implicitly convert type System.linq.iorderedQueryable<> to System.Collection.Generic.List<>

I am getting an error : i am using entity framework, wcf.
Error:cannot implicitly convert type System.linq.iorderedQueryable<xDataModel.Info> to System.Collection.Generic.List<xServiceLibrary.Info>
Below are my code:
WCF Service:
namespace xServiceLibrary
{
public List<Info> GetScenario()
{
xEntities db = new xEntities();
var query = from qinfo in db.Infoes
select qinfo;
//return query.Cast<Info>().ToList(); (not working)
//return query.toList(); (not working)
return query;
}
}
Interface:
namespace xServiceLibrary
{
[OperationContract]
List<Info> GetScenario();
}
Class:
namespace xServiceLibrary
{
[DataContract]
public class Info
{
[DataMember]
public int Scenario_Id;
[DataMember]
public string Scenario_Name { get; set; }
[DataMember]
public string Company_Name { get; set; }
}
}
update:(2)
I have two class library files.
One is xDataModel namespace in which i have created xmodel.edmx file.
second is xServiceLibrary namespace where i am implementing Wcf Service.
i have attached the xDataModel.dll file in my xServiceLibrary so that i could query my EF Model.
i am not able to understand the concept. any help would be appreciated.
The problem is that you have two different types named Info: DataModel.Info and ServiceLibrary.Info - because these are different types you cannot cast one into the other.
If there is no strong reason for both being there I would eliminate one of them. Otherwise as a workaround you could project DataModel.Info to ServiceLibrary.Info by copying the relevant properties one by one:
var results = (from qinfo in db.Infoes
select new ServiceLibrary.Info()
{
Scenario_Id = qinfo.Scenario_Id,
//and so on
}).ToList();
The problem is that you have two different classes, both called Info, both in scope at the time you run your query. This is a very very bad thing, especially if you thought they were the same class.
If DataModel.Info and ServiceLibrary.Info are the same class, you need to figure out why they are both in scope at the same time and fix that.
If they are different classes, you need to be explicit about which one you are trying to return. Assuming that your EF model includes a set of DataModel.Info objects, your options there are:
Return a List<DataModel.Info> which you can get by calling query.ToList()
Return a List<ServiceLibrary.Info> which you can get by copying the fields from your DataModel.Info objects:
var query = from qinfo in db.Info
select new ServiceLibrary.Info
{
Scenario_Id = q.Scenario_Id,
Scenario_Name = q.Scenario_Name
Company_Name = q.Company_Name
};
Return something else, such as your custom DTO object, similar to #2 but with only the specific fields you need (e.g. if ServiceLibrary.Info is a heavy object you don't want to pass around.
In general, though, your problem is centered around the fact that the compiler is interpreting List<Info> as List<ServiceLibrary.Info> and you probably don't want it to.