I'm wanting to only expose a list as ReadOnly but it's, but while trying to accomodate that for Deserialization, it's not currently working.
Firstly, to confirm Serialization:
{
"StartTime": {
"WeightedValues": [
{
"Value": "6",
"Weight": 1.0
},
{
"Value": "7",
"Weight": 1.0
}
]
},
}
This code, with a public List works for both serialization and deserialzation:
internal class PoSet<T>
{
public List<PossibleOutcome<T>> WeightedValues = new();
public PoSet() { }
public PoSet(IEnumerable<PossibleOutcome<T>> weightedValues)
{
if (weightedValues == null)
throw new ArgumentNullException(nameof(weightedValues));
WeightedValues.AddRange(weightedValues);
}
public void Add(PossibleOutcome<T> weightedValue)
{
if (weightedValue == null)
throw new ArgumentNullException(nameof(weightedValue));
WeightedValues.Add(weightedValue);
}
}
...but this code, which exposes just a ReadOnly list and uses a JSON Constructor attribute doesn't works for Serialization but not for Deserialization. I've tried a couple of JSON attribute variations:
internal class PoSet<T>
{
private List<PossibleOutcome<T>> _weightedValues = new();
public IReadOnlyList<PossibleOutcome<T>> WeightedValues => _weightedValues.AsReadOnly();
[JsonConstructor]
public PoSet(List<PossibleOutcome<T>> weightedValues) //Constructor for the deserializer
{
if (weightedValues == null)
throw new ArgumentNullException(nameof(weightedValues));
_weightedValues.AddRange(weightedValues);
}
public PoSet() { }
public PoSet(IEnumerable<PossibleOutcome<T>> weightedValues)
{
if (weightedValues == null)
throw new ArgumentNullException(nameof(weightedValues));
_weightedValues.AddRange(weightedValues);
}
public void Add(PossibleOutcome<T> weightedValue)
{
if (weightedValue == null)
throw new ArgumentNullException(nameof(weightedValue));
_weightedValues.Add(weightedValue);
}
}
Any help much appreciated. Surely this is possible. I've read a little about contracts but that seems beyond my abilities (this is hobby stuff; I'm not a real programmer).
BTW If it helps, this is the PossibleOutcome class:
// Generic WeightedValue class (for any type T)
internal class PossibleOutcome<T>
{
public T Value { get; set; }
public double Weight { get; set; }
public PossibleOutcome() { } // Parameterless constructor for deserialization
public PossibleOutcome(T value, double weight)
{
if (weight < 0)
throw new ArgumentException("Weight cannot be negative.", nameof(weight));
Value = value;
Weight = weight;
}
}
I'm wanting to only expose a list as ReadOnly but it's, but while trying to accomodate that for Deserialization, it's not currently working.
Firstly, to confirm Serialization:
{
"StartTime": {
"WeightedValues": [
{
"Value": "6",
"Weight": 1.0
},
{
"Value": "7",
"Weight": 1.0
}
]
},
}
This code, with a public List works for both serialization and deserialzation:
internal class PoSet<T>
{
public List<PossibleOutcome<T>> WeightedValues = new();
public PoSet() { }
public PoSet(IEnumerable<PossibleOutcome<T>> weightedValues)
{
if (weightedValues == null)
throw new ArgumentNullException(nameof(weightedValues));
WeightedValues.AddRange(weightedValues);
}
public void Add(PossibleOutcome<T> weightedValue)
{
if (weightedValue == null)
throw new ArgumentNullException(nameof(weightedValue));
WeightedValues.Add(weightedValue);
}
}
...but this code, which exposes just a ReadOnly list and uses a JSON Constructor attribute doesn't works for Serialization but not for Deserialization. I've tried a couple of JSON attribute variations:
internal class PoSet<T>
{
private List<PossibleOutcome<T>> _weightedValues = new();
public IReadOnlyList<PossibleOutcome<T>> WeightedValues => _weightedValues.AsReadOnly();
[JsonConstructor]
public PoSet(List<PossibleOutcome<T>> weightedValues) //Constructor for the deserializer
{
if (weightedValues == null)
throw new ArgumentNullException(nameof(weightedValues));
_weightedValues.AddRange(weightedValues);
}
public PoSet() { }
public PoSet(IEnumerable<PossibleOutcome<T>> weightedValues)
{
if (weightedValues == null)
throw new ArgumentNullException(nameof(weightedValues));
_weightedValues.AddRange(weightedValues);
}
public void Add(PossibleOutcome<T> weightedValue)
{
if (weightedValue == null)
throw new ArgumentNullException(nameof(weightedValue));
_weightedValues.Add(weightedValue);
}
}
Any help much appreciated. Surely this is possible. I've read a little about contracts but that seems beyond my abilities (this is hobby stuff; I'm not a real programmer).
BTW If it helps, this is the PossibleOutcome class:
// Generic WeightedValue class (for any type T)
internal class PossibleOutcome<T>
{
public T Value { get; set; }
public double Weight { get; set; }
public PossibleOutcome() { } // Parameterless constructor for deserialization
public PossibleOutcome(T value, double weight)
{
if (weight < 0)
throw new ArgumentException("Weight cannot be negative.", nameof(weight));
Value = value;
Weight = weight;
}
}
Share
Improve this question
edited Mar 19 at 6:42
DarkBee
15.5k8 gold badges72 silver badges117 bronze badges
asked Mar 19 at 3:34
MrGregglesMrGreggles
6,17510 gold badges43 silver badges52 bronze badges
2
- 1 It would be helpful to know which JSON library you're using. – ProgrammingLlama Commented Mar 19 at 3:57
- Nothing special: using System.Text.Json.Serialization; in .NET – MrGreggles Commented Mar 19 at 6:04
1 Answer
Reset to default 3I think the library you are using is System.Text.Json because Json.Net can deserialize this class normally. The JsonConstructor
rule of System.Text.Json is somewhat wooden, it requires that each parameter must be able to match a property (or field), their names and types must be consistent (name is case-insensitive), so you need to change the parameter type to IReadOnlyList<PossibleOutcome<T>>
.