Если кому-то нужно использовать JsonPathConverter @BrianRogers также с опцией WriteJson
, вот решение (которое работает только для путей только с точками):
Удалите свойство CanWrite
, чтобы он снова становится true
.
Замените код WriteJson
следующим образом:
public override void WriteJson(JsonWriter writer, object value,
JsonSerializer serializer)
{
var properties = value.GetType().GetRuntimeProperties ().Where(p => p.CanRead && p.CanWrite);
JObject main = new JObject ();
foreach (PropertyInfo prop in properties) {
JsonPropertyAttribute att = prop.GetCustomAttributes(true)
.OfType<JsonPropertyAttribute>()
.FirstOrDefault();
string jsonPath = (att != null ? att.PropertyName : prop.Name);
var nesting=jsonPath.Split(new[] { '.' });
JObject lastLevel = main;
for (int i = 0; i < nesting.Length; i++) {
if (i == nesting.Length - 1) {
lastLevel [nesting [i]] = new JValue(prop.GetValue (value));
} else {
if (lastLevel [nesting [i]] == null) {
lastLevel [nesting [i]] = new JObject ();
}
lastLevel = (JObject)lastLevel [nesting [i]];
}
}
}
serializer.Serialize (writer, main);
}
Как я уже говорил, это работает только для путей, содержащих точки. Учитывая это, вы должны добавить следующий код в ReadJson
, чтобы предотвратить другие случаи:
[...]
string jsonPath = (att != null ? att.PropertyName : prop.Name);
if (!Regex.IsMatch(jsonPath, @"^[a-zA-Z0-9_.-]+$")) {
throw new InvalidOperationException("JProperties of JsonPathConverter can have only letters, numbers, underscores, hiffens and dots."); //Array operations not permitted
}
JToken token = jo.SelectToken(jsonPath);
[...]
Нет, нет встроенной возможности устанавливать значение свойства с метаданными. Вы могли бы использовать какую-то фабрику, которая создала бы экземпляры класса с отражением, а затем могла бы установить значения по умолчанию. Но вкратце, вам нужно использовать конструкторы (или установщики полей ..., которые поднимаются в конструкторе.), Чтобы установить значения по умолчанию.
Если у вас есть несколько перегрузок для вашего конструктора, вы можете посмотреть цепочку конструктора .
Используя C # 6+, вы можете сделать что-то вроде этого ...
public string MyValue { get; set; } = "My Default";
О, это становится веселее, потому что люди даже просили что-то подобное ...
public string MyValue {
private string _myValue;
get { return _myValue ?? "My Default"; }
set { _myValue = value; }
}
... преимущество в том, что вы можете контролировать область поля, чтобы быть доступными только в коде свойства, чтобы вам не приходилось беспокоиться о том, что в вашем классе ничего не играет с состоянием, не используя геттер / сеттер.
Если вы используете C # 5 и более ранние версии, вы должны сделать это в конструкторе.
, но начиная с C # 6.0, возможность иметь авто инициализаторы свойств включена, и синтаксис:
public int myage { get; set; } = 33;
Присвоить значение свойства по умолчанию в конструкторе класса.
class MyClass
{
public MyClass()
{
IsTrue = true;
IsFalse = false;
}
public bool IsTrue { get; set; }
public bool IsFalse { get; set; }
[...]
public void Something()
{
var isTrue = this.IsTrue;
var isFalse = this.IsFalse;
}
}
В этом очень конкретном примере вы вроде бы можете:
public bool IsFalse { get; set; }
public bool IsTrue
{
get { return !IsFalse; }
set { IsFalse = !value; }
}
public void Something()
{
var isTrue = this.IsTrue;
var isFalse = this.IsFalse;
}
Но, в общем, нет.