| 735 | } |
| 736 | |
| 737 | func handleMapAny(r Registry, s *Schema, path *PathBuffer, mode ValidateMode, m map[any]any, res *ValidateResult) { |
| 738 | if s.MinProperties != nil { |
| 739 | if len(m) < *s.MinProperties { |
| 740 | res.Add(path, m, s.msgMinProperties) |
| 741 | } |
| 742 | } |
| 743 | if s.MaxProperties != nil { |
| 744 | if len(m) > *s.MaxProperties { |
| 745 | res.Add(path, m, s.msgMaxProperties) |
| 746 | } |
| 747 | } |
| 748 | |
| 749 | for _, k := range s.propertyNames { |
| 750 | v := s.Properties[k] |
| 751 | |
| 752 | // Schemas are generated such that the read/write-only properties are set |
| 753 | // alongside the `$ref`, if it is present (i.e. for objects). If not, |
| 754 | // then the read/write-only properties are set directly on the schema and |
| 755 | // the `for` loop never runs. |
| 756 | readOnly := v.ReadOnly |
| 757 | writeOnly := v.WriteOnly |
| 758 | for v.Ref != "" { |
| 759 | v = r.SchemaFromRef(v.Ref) |
| 760 | } |
| 761 | |
| 762 | // We should be permissive by default to enable easy round-trips for the |
| 763 | // client without needing to remove read-only values. |
| 764 | // TODO: should we make this configurable? |
| 765 | |
| 766 | // Be stricter for responses, enabling validation of the server if desired. |
| 767 | if mode == ModeReadFromServer && writeOnly && m[k] != nil && !reflect.ValueOf(m[k]).IsZero() { |
| 768 | res.Add(path, m[k], "write only property is non-zero") |
| 769 | continue |
| 770 | } |
| 771 | |
| 772 | if _, ok := m[k]; !ok { |
| 773 | if !s.requiredMap[k] { |
| 774 | continue |
| 775 | } |
| 776 | if (mode == ModeWriteToServer && readOnly) || |
| 777 | (mode == ModeReadFromServer && writeOnly) { |
| 778 | // These are not required for the current mode. |
| 779 | continue |
| 780 | } |
| 781 | res.Add(path, m, s.msgRequired[k]) |
| 782 | continue |
| 783 | } |
| 784 | |
| 785 | if m[k] == nil && (!s.requiredMap[k] || s.Nullable) { |
| 786 | // This is a non-required field which is null, or a nullable field set |
| 787 | // to null, so ignore it. |
| 788 | continue |
| 789 | } |
| 790 | |
| 791 | if m[k] != nil && s.DependentRequired[k] != nil { |
| 792 | for _, dependent := range s.DependentRequired[k] { |
| 793 | if m[dependent] != nil { |
| 794 | continue |