संकट

मैं .NET 5 के साथ ASP.NET कोर का उपयोग कर रहा हूं और System.Text.Json धारावाहिक प्रकार का उपयोग कर रहा हूं जिसमें फ़ील्ड युक्त प्रकार हैं (जैसे System.Numerics.Vector3 (X, Y और Z फ़ील्ड हैं), हालांकि फ़ील्ड के साथ कोई भी प्रकार व्यवहार करता है मुझे भी)।

मैंने सत्यापित किया है कि पोस्टमैन पर एपीआई को कॉल करके फ़ील्ड ठीक से क्रमबद्ध हो जाते हैं, हालांकि स्वाशबकल द्वारा उत्पन्न स्वैगर एपीआई परिभाषा इसे ठीक से प्रतिबिंबित नहीं करती है। (परिभाषा सिर्फ एक खाली प्रकार दिखाती है)

रेप्रो

मैंने एक gist बनाया है जो इसे पुन: उत्पन्न करता है। यह /api/Test पर एक HTTP प्राप्त विधि प्रदान करता है जो एक फ़ील्ड और एक संपत्ति के साथ Test प्रकार की वस्तु देता है। दोनों तार हैं। डाकिया के माध्यम से इस एपीआई को कॉल करना दोनों के लिए सही मान देता है। स्वैगर यूआई को /swagger पर या परिभाषा को /swagger/v1/swagger.json पर देखने से ही संपत्ति का पता चलता है।

यह व्यवहार स्वैगर UI के उदाहरणों पर भी लागू होता है, जिसमें केवल गुण शामिल होते हैं।

अपेक्षित व्यवहार

दस्तावेज़ों के अनुसार स्वैगर जेनरेटर को स्वतः System.Text.Json के व्यवहार की प्रतिलिपि बनानी चाहिए, जो स्पष्ट रूप से फ़ील्ड को क्रमबद्ध करने के लिए कॉन्फ़िगर किया गया है (देखें पंक्ति 47), इसलिए मैं उम्मीद करता हूं कि स्वैगर परिभाषा में फ़ील्ड शामिल हो।

सारांश

दोहराने के लिए, मैं सार्वजनिक क्षेत्रों के साथ एक प्रकार को क्रमबद्ध करने के लिए System.Text.Json का उपयोग करता हूं। यह काम करता है, और मैं इसे इस तरह रखना पसंद करूंगा।

मैं एपीआई के दस्तावेज उत्पन्न करने के लिए स्वाशबकल का उपयोग करने का प्रयास करता हूं जो इन क्रमिकरणों को लौटाता है। यह केवल गुणों के लिए काम करता है, लेकिन फ़ील्ड के लिए नहीं।

क्या ऐसा कुछ और है जिसे काम करने के लिए स्पष्ट रूप से कॉन्फ़िगर करने की आवश्यकता है?

12
blenderfreaky 27 नवम्बर 2020, 13:20

2 जवाब

सबसे बढ़िया उत्तर

ऐसा लगता है कि Swashbuckle दस्तावेज़ बनाने के लिए JsonSerializerOptions का उपयोग नहीं करता है। मुझे मिला एक कामकाज मैन्युअल रूप से प्रकारों को संभालना है:

public class FieldsSchemaFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        var fields = context.Type.GetFields();

        if (fields == null) return;
        if (fields.Length == 0) return;

        foreach (var field in fields)
        {
            schema.Properties[field.Name] = new OpenApiSchema
            {
                // this should be mapped to an OpenApiSchema type
                Type = field.FieldType.Name
            };
        }
    }
}

फिर अपने Startup.cs ConfigureServices में:

services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApplication1", Version = "v1" });
    c.SchemaFilter<FieldsSchemaFilter>();
});

आगे बढ़ते समय, आप SchemaFilterContext (SchemaGenerator) में प्रयुक्त JsonSerializerOptions देखेंगे। IncludeFields सत्य पर सेट है। डॉक्स के लिए अभी भी केवल गुणों का उपयोग किया जाता है, इसलिए मुझे लगता है कि इस तरह का एक फ़िल्टर आपकी सबसे अच्छी शर्त है।

7
Markus Dresch 9 पद 2020, 12:27

इस मुद्दे का स्वैगर से कोई लेना-देना नहीं है, यह शुद्ध क्रमांकन मुद्दा है।

आपके पास 3 समाधान हैं:

  1. वेक्टर के लिए अपना खुद का अनुकूलित जेसन लिखें। (सिर्फ अवधारणा)
  2. आदिम प्रकार के साथ एक अनुकूलित वस्तु का प्रयोग करें और इसे मैप करें। (सिर्फ अवधारणा)
  3. Newtonsoft.Json (सुझाए गए समाधान) का प्रयोग करें

माइक्रोसॉफ्ट के संबंध में doc, System.Text.Json आप तुलना सूची में देख सकते हैं कि System.Text.Json में कुछ सीमाएँ हो सकती हैं।

यदि आप चाहते हैं कि सुझाए गए समाधान सीधे समाधान 3 पर जाएं।

आइए कस्टम की पहली अवधारणा लेते हैं क्रमबद्ध। बीटीडब्ल्यू यह कस्टम उदाहरण सिर्फ प्रदर्शन के लिए है और पूर्ण समाधान नहीं है।

तो आप क्या कर सकते हैं निम्नलिखित है:

  1. एक कस्टम वेक्टर CustomVector मॉडल बनाएं।
  2. एक कस्टम VectorConverter वर्ग बनाएं जो JsonConverter का विस्तार करे।
  3. कुछ मैपिंग जोड़ा गया।
  4. VectorConverter विशेषता को वेक्टर गुण में रखें।

यहाँ मेरा प्रयास है CustomVector:

public class CustomVector
{
    public float? X { get; set; }
    public float? Y { get; set; }
    public float? Z { get; set; }
}

और कस्टम वेक्टर कनवर्टर:

public class VectorConverter : JsonConverter<Vector3>
{
    public override Vector3 Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        // just for now
        return new Vector3();
    }

    public override void Write(Utf8JsonWriter writer, Vector3 data, JsonSerializerOptions options)
    {
        // just for now
        var customVector = new CustomVector
        {
            X = data.X,
            Y = data.Y,
            Z = data.Z
        };

        var result = JsonSerializer.Serialize(customVector);

        writer.WriteStringValue(result);
    }
}

और आप वेक्टर संपत्ति, निम्नलिखित विशेषता जोड़ा:

[JsonConverter(typeof(VectorConverter))]
public Vector3 Vector { get; set; }

यह निम्नलिखित परिणाम लौटाएगा:

enter image description here

अब यह समस्या का हिस्सा हल करता है, यदि आप एक वेक्टर ऑब्जेक्ट पोस्ट करना चाहते हैं, तो आपके पास एक और चुनौती होगी, जो आपके कार्यान्वयन तर्क पर भी निर्भर करती है।

इसलिए, मेरा दूसरा समाधान प्रयास आता है जहां हम अपने कस्टम वेक्टर का पर्दाफाश करते हैं और json में वेक्टर 3 को अनदेखा करते हैं और इसे हमारे कोड से वेक्टर 3 से/मैप करते हैं:

इसलिए हमने एक CustomVector पेश किया है, हम इसे अपने वेक्टर3 में मैप करने के बजाय अपने मॉडल में वेक्टर3 के स्थान पर उपयोग कर सकते हैं।

public class Test
{
    public string Field { get; set; }
    public string Property { get; set; }
    [JsonIgnore]
    public Vector3 Vector { get; set; }
    public CustomVector CustomVector { get; set; }
}

enter image description here

मैपिंग उदाहरण के साथ एक प्राप्त और पोस्ट विधि यहां दी गई है:

[HttpGet]
public Test Get()
{
    var vector = new CustomVector() { X = 1, Y = 1, Z = 1 };
    var test = new Test
    {
        Field = "Field",
        Property = "Property",
        CustomVector = vector
    };
    VectorMapping(test);
    return test;
}

[HttpPost]
public Test Post(Test test)
{
    VectorMapping(test);
    return test;
}

private static void VectorMapping(Test test)
{
    test.Vector = new Vector3
    {
        X = test.CustomVector.X.GetValueOrDefault(),
        Y = test.CustomVector.Y.GetValueOrDefault(),
        Z = test.CustomVector.Z.GetValueOrDefault()
    };
}

पहले समाधान में नीचे की ओर, हमें एक पूर्ण अनुकूलित क्रमांकन लिखने की आवश्यकता है, और हमारे दूसरे समाधान में हमने अतिरिक्त मॉडल और मानचित्रण पेश किया है।

सुझाया समाधान

इसलिए मैं निम्नलिखित और तीसरे प्रयास का सुझाव देता हूं:

आपके पास जो कुछ भी है उसे अपने समाधान में रखें, बस अपने प्रोजेक्ट में nuget Swashbuckle.AspNetCore.Newtonsoft जोड़ा, जैसे:

<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="5.6.3" />

और आपके स्टार्टअप में

services.AddSwaggerGenNewtonsoftSupport();

फायर अप, और यह दस्तावेज़ीकरण उत्पन्न करेगा, क्योंकि यह वेक्टर 3 और अन्य वर्ग प्रकारों को क्रमबद्ध और deserializing की अनुमति देता है जो System.Text.Json द्वारा समर्थित नहीं हैं।

जैसा कि आप देख सकते हैं कि इसमें अब वेक्टर 3 को दस्तावेज़ीकरण में शामिल किया गया है:

enter image description here

मुझे पूरा यकीन है कि यह अन्य तरीकों से किया जा सकता है। तो इसे हल करने का यह मेरा प्रयास है।

4
maytham-ɯɐɥʇʎɐɯ 9 पद 2020, 03:05