How to ignore global JsonStringEnumConverter for specific enum type - asp.net-core-3.1

Is there a way to annotate a POCO so that the JsonStringEnumConverter is ignored?
I currently have this configured in my Startup class:
mvcBuilder.AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
// ... other options ...
});
But then I have an enum which I want to be serialized with the numberic value and not the string value
[JsonConverter(typeof(... what goes here ...)]
public enum TypeIdentifier
{
value1,
value2
}
expected serialisation:
{
"myProperty":1
}

Related

Swift nested generic parameter inference

Swift 5.1 .
Consider the following code. I don't have a problem, exactly, but my code is a little redundant and it's kinda annoying, so I'm wondering if there's a way to tell Swift to infer one of the generic parameters.
public class X0 {
}
public class X1: X0 {
}
public class C0<CONTAINED> {
public var value: CONTAINED
public init(_ value: CONTAINED) {
self.value = value
}
}
public class C1<T: X0>: C0<T> {
}
//public class CA<BOX: C0> { // ERROR Reference to generic type 'C0' requires arguments in <...>
public class CA<BOX: C0<T>, T> { // It's inconvenient that I have to give T as a parameter of the outer class; seems like it could be inferred
}
public func test() {
// let v: CA<C1<X1>> // ERROR Generic type 'CA' specialized with too few type parameters (got 1, but expected 2)
let v: CA<C1<X1>, X1> // This here is a little inconvenient to type, particularly when the class names are longer.
}
The two X1 have to be equal, it seems - I tried CA<C1<X0>,X1> and CA<C1<X1>,X0> just in case there was some logical gotcha I missed, but it gave me errors for both, so I think the two are required to be exactly equal, so inference should be theoretically permitted, at least.
Is there a way to tell Swift to infer the duplicate type parameter? I tried _ in a few places, and omitting the parameter, but it gave me errors.
You can only clean it up with protocols.
You can't put protocols inside of types so the naming has to look like Objective-C.
Use camel case!
public class C0<🐫> {
public var value: 🐫
public init(_ value: 🐫) {
self.value = value
}
}
public protocol C0Protocol {
associatedtype 🐫
}
extension C0: C0Protocol { }
public class CA<C0: C0Protocol> { }
public func test() {
let v: CA< C1<X1> >
}

Dart : Read annotated value of a field

I have a Dart enum which looks like this:
enum Gender {
#JsonValue(0)
male,
#JsonValue(1)
female,
}
I have created a dart extension that returns the String name and int value. It looks something like this -
extension GenderExtention on Gender {
String get name {
switch (this) {
default:
return _getDefaultName(this);
}
}
//For the enum male, it returns "Male"
String _getDefaultName(Community value) {
if (value == null) {
return null;
}
String valueStr = value.toString();
String enumName = valueStr.substring(valueStr.indexOf('.') + 1);
return enumName[0].toUpperCase() + enumName.substring(1);
}
int get value {
switch (this) {
case Gender.male:
return 0;
case Gender.female:
return 1;
default:
return null;
}
}
}
This becomes painful for larger enums, especially the value section.
Are there any suggestions on how to get the enum value (0 for #JsonValue(0)) more easily than manually defining it in the extension? Would using something like reflections help here?
the only way to access annotations at run-time is indeed reflection using dart:mirrors. That library is not available when compiling to the web or for Flutter, so it's probably not going to solve your problem.
What you can do here is:
int get value => this.index;
That only works if the values are actually the same as the index (0 for the first declared value, 1 for the next, etc.)

Unable to make a protocol for enum

I am not very good with protocols, and I'm quite stuck right now. I am trying to make a protocol for an enum, which has a name property (or function if it needs to be).
This will allow me to get the name of an enum value, similar to conforming to String alone, but with the first letter capitalised instead. For example, what I want to happen:
enum Furniture: Named {
case table, chair, lamp
}
Furniture.table.name // Returns 'Table'
Furniture.chair.name // Returns 'Chair'
Furniture.lamp.name // Returns 'Lamp'
Here is what I have so far:
protocol Named {
var name: String { get }
}
extension Named where Named: String {
var name: String {
let str: String = self.rawValue
return str.prefix(1).uppercased() + str.dropFirst()
}
}
This gives me errors, and when I try to correct them, another error pops up.
Right now, this shows me the following errors:
Type 'Named' constrained to non-protocol, non-class type 'String'
Value of type 'Self' has no member 'rawValue'
How can I fix this?
Enums get their raw value via the RawRepresentable protocol, so that's what you should use when constraining your extension:
extension Named where Self: RawRepresentable, RawValue == String {
var name: String {
let str: String = self.rawValue
return str.prefix(1).uppercased() + str.dropFirst()
}
}
You also need to declare that your enum uses a String as the type of its rawValue:
enum Furniture: String, Named {
case table, chair, lamp
}
Set the Furniture enum to a string raw type, the Swift compiler automatically adds RawRepresentable conformance.
protocol Named {
var name: String { get }
}
enum Furniture: String, Named {
case table, chair, lamp
}
extension Named where Self: RawRepresentable, RawValue == String {
var name: String {
return rawValue.capitalized
}
}
A Unit Tests to validate the Furniture enum,
import XCTest
class FurnitureTests: XCTestCase {
func testEnumDisplayNameFirstLetterCapitlized() {
XCTAssertEqual(Furniture.table.name, "Table")
XCTAssertEqual(Furniture.chair.name, "Chair")
XCTAssertEqual(Furniture.lamp.name, "Lamp")
}
func testEnumRawValue() {
XCTAssertEqual(Furniture.table.rawValue, "table")
XCTAssertEqual(Furniture.chair.rawValue, "chair")
XCTAssertEqual(Furniture.lamp.rawValue, "lamp")
}
}

Angular 5 models httpClient type casting

I declare a model in ingredient.model.ts
export class Ingredient {
constructor(private name: string, public amount: number) {}
getName() { return this.name }
}
In ingredients.service.ts, if I get them in this way:
httpClient.get<Ingredient>(url).subscribe(
(igredient) => {
console.log(igredient.getName());
});
It gives errors in console, such as "no method getName in property igredient".
Also, whenever I try to declare a property type Category[] it fails, but Array seems working fine.
Edit:
I want to provide more info.
Given the Igredient model and the following JSON structure:
{
name: "Apple",
amount: "5",
created_at: "date",
}
The Igredient constructor isn't even invoked, therefore the GET payload won't be parsed.
You'll need to use a property, not a method. The returned object is really a json object, and there is no such thing as "getName()" method (despite your effort to add a type information). Try something like this:
export interface Ingredient {
strin: string,
amount: number,
created_at: string
}
httpClient.get<Ingredient>(url).subscribe(
(igredient) => {
console.log(igredient.amount);
});
EDIT: You need to provide a type information based on the expected json object. If the returned json object has attributes, strin, amount, and created_at, then you need to define a type that is compatible with the expected json object.
In angular 5, You can do this:
export interface Deserializable<T> {
deserialize(input: any): T;
}
export class Ingredient implments Deserializable<Ingredient>{
constructor(private name: string, public amount: number) {}
deserialize(input: any): Project {
Object.assign(this, input);
// do nested thing here -pop arrays of nested objects and create them
}
return this;
}
now in your service:
httpClient.get<Ingredient>(url).pipe(map(elem=>this.foo(elem)))
.subscribe((igredient) => {console.log(igredient.getName());
});
foo(ingredient:Ingrdient){
var i = new Ingridiant().desrialize(ingredient)
}
after the map you will have the Ingradient class, not the object.

How do I get a CustomStringConvertible description from this enum?

I have the following enum
enum Properties: CustomStringConvertible {
case binaryOperation(BinaryOperationProperties),
brackets(BracketsProperties),
chemicalElement(ChemicalElementProperties),
differential(DifferentialProperties),
function(FunctionProperties),
number(NumberProperties),
particle(ParticleProperties),
relation(RelationProperties),
stateSymbol(StateSymbolProperties),
symbol(SymbolProperties)
}
and the structs all look like this
struct BinaryOperationProperties: Decodable, CustomStringConvertible {
let operation: String
var description: String { return operation }
}
So how do I make that enum conform to CustomStringConvertible? I tried with a simple getter but obviously that calls itself and I'd like to call the specific struct's instead.
Bonus points: does an enum defined like that have a name?
Such an enum is called enum with associated values.
I'd implement description by manually switching over the cases:
extension Properties: CustomStringConvertible {
var description: String {
switch self {
case .binaryOperation(let props):
return "binaryOperation(\(props))"
case .brackets(let props):
return "brackets(\(props))"
...
}
}
}
Edit: an alternative is to use Swift's Mirror reflection API. The enum case of an instance is listed as the mirror's child and you can print its label and value like this:
extension Properties: CustomStringConvertible {
var description: String {
let mirror = Mirror(reflecting: self)
var result = ""
for child in mirror.children {
if let label = child.label {
result += "\(label): \(child.value)"
} else {
result += "\(child.value)"
}
}
return result
}
}
(This is a generic solution that should be usable for many types, not just enums. You'll probably have to add some line breaks for types that have more than a single child.)
Edit 2: Mirror is also what print and String(describing:) use for types that don't conform to Custom[Debug]StringConvertible. You can check out the source code here.