RicoSuter / NJsonSchema

JSON Schema reader, generator and validator for .NET
http://NJsonSchema.org
MIT License
1.4k stars 535 forks source link

How to dereference $refs to Definitions #889

Open sasavasiljevic opened 5 years ago

sasavasiljevic commented 5 years ago

Hi Is there a possibility to dereference some $refs to definitions in JSON schema? I would like to bloat some references to embedded objects (practically to copy definition from definitions inside a property that references its definition).

sasavasiljevic commented 5 years ago

If anyone bumps here, then here is my solution on how to dereference all refs:

private JsonSchema4 DereferenceSchema(JsonSchema4 schema)
{
    if (schema.IsArray)
    {
        if (schema.Item != null)
        {
            schema.Item = DereferenceSchema(schema.Item);
        }
    }
    else if (schema.AllOf.Count > 0)
    {
        foreach (JsonSchema4 subSchema in schema.AllOf.ToList())
        {
            JsonSchema4 dereferencedSchema = DereferenceSchema(subSchema);
            schema.AllOf.Remove(subSchema);
            schema.AllOf.Add(dereferencedSchema);
        }
    }
    else if (schema.AnyOf.Count > 0)
    {
        foreach (JsonSchema4 subSchema in schema.AnyOf.ToList())
        {
            JsonSchema4 dereferencedSchema = DereferenceSchema(subSchema);
            schema.AnyOf.Remove(subSchema);
            schema.AnyOf.Add(dereferencedSchema);
        }
    }
    else if (schema.OneOf.Count > 0)
    {
        foreach (JsonSchema4 subSchema in schema.OneOf.ToList())
        {
            JsonSchema4 dereferencedSchema = DereferenceSchema(subSchema);
            schema.OneOf.Remove(subSchema);
            schema.OneOf.Add(dereferencedSchema);
        }
    }
    else if (schema.HasReference)
    {
        return DereferenceSchema(schema.Reference);
    }
    else
    {
        foreach (string propertyName in schema.Properties.Keys.ToList())
        {
            schema.Properties[propertyName] = GetPropertyFromSchema(DereferenceSchema(schema.Properties[propertyName]));
        }
    }
    schema.Definitions.Clear();
    return schema;
}

private JsonProperty GetPropertyFromSchema(JsonSchema4 schema)
{
    var data = JsonConvert.SerializeObject(schema);
    var property = JsonConvert.DeserializeObject<JsonProperty>(data);
    return property;
}

Hope this will help someone :)

dnitsch commented 1 year ago

thanks for this!

Below is a slight update for the latest version of the lib

     ///<summary>
    /// Dereferences a schema against created `definitions` block. 
    ///</summary>
    ///<remarks>
    /// Taken from this [issue](https://github.com/RicoSuter/NJsonSchema/issues/889). 
    /// Adjusted for System.Text.Json update.
    ///</remarks>
    private JsonSchema DereferenceSchema(JsonSchema schema)
    {
        if (schema.IsArray)
        {
            if (schema.Item != null)
            {
                schema.Item = DereferenceSchema(schema.Item);
            }
        }
        else if (schema.AllOf.Count > 0)
        {
            foreach (JsonSchema subSchema in schema.AllOf.ToList())
            {
                JsonSchema dereferencedSchema = DereferenceSchema(subSchema);
                schema.AllOf.Remove(subSchema);
                schema.AllOf.Add(dereferencedSchema);
            }
        }
        else if (schema.AnyOf.Count > 0)
        {
            foreach (JsonSchema subSchema in schema.AnyOf.ToList())
            {
                JsonSchema dereferencedSchema = DereferenceSchema(subSchema);
                schema.AnyOf.Remove(subSchema);
                schema.AnyOf.Add(dereferencedSchema);
            }
        }
        else if (schema.OneOf.Count > 0)
        {
            foreach (JsonSchema subSchema in schema.OneOf.ToList())
            {
                JsonSchema dereferencedSchema = DereferenceSchema(subSchema);
                schema.OneOf.Remove(subSchema);
                schema.OneOf.Add(dereferencedSchema);
            }
        }
        else if (schema.HasReference)
        {   
            return DereferenceSchema(schema.Reference);
        }
        else
        {
            foreach (string propertyName in schema.Properties.Keys.ToList())
            {
                try {
                    schema.Properties[propertyName] = DereferenceSchema(schema.Properties[propertyName]) as JsonSchemaProperty;
                } catch (Exception ex) {
                    // handle error....
                }
            }
        }
        schema.Definitions.Clear();
        return schema;
    }

Hope it helps others too...