JSON을 사용한 시리얼화된 필드의 순서.그물
JSON을 사용하여 직렬화된 JSON 개체의 필드 순서를 지정할 수 있는 방법이 있습니까?인터넷?
항상 단일 필드가 먼저 표시되도록 지정하면 됩니다.
지원되는 방법은JsonProperty
순서를 설정할 클래스 속성에서 속성을 선택합니다.자세한 내용은 JsonPropertyAttribute 주문 문서를 참조하십시오.
패스 더JsonProperty
한 사람Order
나머지는 시리얼라이저가 처리합니다.
[JsonProperty(Order = 1)]
이것은 와 매우 유사합니다.
DataMember(Order = 1)
의System.Runtime.Serialization
날들.
여기 @kevin-babcock의 중요한 메모가 있습니다.
... 주문을 1로 설정하는 것은 다른 모든 속성에서 1보다 큰 주문을 설정하는 경우에만 작동합니다.기본적으로 Order 설정이 없는 속성에는 -1의 순서가 지정됩니다.따라서 모든 일련화된 속성과 순서를 지정하거나 첫 번째 항목을 -2로 설정해야 합니다.
실제로 순서를 제어할 수 있습니다.IContractResolver
또는 덮어쓰기DefaultContractResolver
의CreateProperties
방법.
여기 간단한 구현의 예가 있습니다.IContractResolver
속성을 알파벳 순으로 정렬합니다.
public class OrderedContractResolver : DefaultContractResolver
{
protected override System.Collections.Generic.IList<JsonProperty> CreateProperties(System.Type type, MemberSerialization memberSerialization)
{
return base.CreateProperties(type, memberSerialization).OrderBy(p => p.PropertyName).ToList();
}
}
그런 다음 설정을 설정하고 개체를 직렬화하면 JSON 필드가 알파벳 순서로 표시됩니다.
var settings = new JsonSerializerSettings()
{
ContractResolver = new OrderedContractResolver()
};
var json = JsonConvert.SerializeObject(obj, Formatting.Indented, settings);
내 경우 마티아스의 답변은 효과가 없었다.그CreateProperties
메서드가 호출되지 않았습니다.
디버깅 후Newtonsoft.Json
내부적으로는 다른 해결책이 떠올랐어요
public class JsonUtility
{
public static string NormalizeJsonString(string json)
{
// Parse json string into JObject.
var parsedObject = JObject.Parse(json);
// Sort properties of JObject.
var normalizedObject = SortPropertiesAlphabetically(parsedObject);
// Serialize JObject .
return JsonConvert.SerializeObject(normalizedObject);
}
private static JObject SortPropertiesAlphabetically(JObject original)
{
var result = new JObject();
foreach (var property in original.Properties().ToList().OrderBy(p => p.Name))
{
var value = property.Value as JObject;
if (value != null)
{
value = SortPropertiesAlphabetically(value);
result.Add(property.Name, value);
}
else
{
result.Add(property.Name, property.Value);
}
}
return result;
}
}
제 경우 어레이 내의 오브젝트를 처리하지 않았기 때문에 niaher의 솔루션이 작동하지 않았습니다.
그의 해결책을 바탕으로 제가 생각해낸 것은 이것입니다.
public static class JsonUtility
{
public static string NormalizeJsonString(string json)
{
JToken parsed = JToken.Parse(json);
JToken normalized = NormalizeToken(parsed);
return JsonConvert.SerializeObject(normalized);
}
private static JToken NormalizeToken(JToken token)
{
JObject o;
JArray array;
if ((o = token as JObject) != null)
{
List<JProperty> orderedProperties = new List<JProperty>(o.Properties());
orderedProperties.Sort(delegate(JProperty x, JProperty y) { return x.Name.CompareTo(y.Name); });
JObject normalized = new JObject();
foreach (JProperty property in orderedProperties)
{
normalized.Add(property.Name, NormalizeToken(property.Value));
}
return normalized;
}
else if ((array = token as JArray) != null)
{
for (int i = 0; i < array.Count; i++)
{
array[i] = NormalizeToken(array[i]);
}
return array;
}
else
{
return token;
}
}
}
이는 일반 클래스, 사전 및 ExpandoObject(동적 객체)에도 적용됩니다.
class OrderedPropertiesContractResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(System.Type type, MemberSerialization memberSerialization)
{
var props = base.CreateProperties(type, memberSerialization);
return props.OrderBy(p => p.PropertyName).ToList();
}
}
class OrderedExpandoPropertiesConverter : ExpandoObjectConverter
{
public override bool CanWrite
{
get { return true; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var expando = (IDictionary<string, object>)value;
var orderedDictionary = expando.OrderBy(x => x.Key).ToDictionary(t => t.Key, t => t.Value);
serializer.Serialize(writer, orderedDictionary);
}
}
var settings = new JsonSerializerSettings
{
ContractResolver = new OrderedPropertiesContractResolver(),
Converters = { new OrderedExpandoPropertiesConverter() }
};
var serializedString = JsonConvert.SerializeObject(obj, settings);
만약 당신이 아마도 의도하지 않은 번호 체계를 생각하지 않고 하나의 속성을 앞으로 끌어내고 싶다면, 그냥 사용하세요.int.MinValue
.
[JsonProperty(Order = int.MinValue)]
Charlie가 지적한 바와 같이 클래스 자체의 속성을 정렬함으로써 JSON 속성의 순서를 어느 정도 제어할 수 있습니다.안타깝게도 이 접근 방식은 기본 클래스에서 상속된 속성에는 적용되지 않습니다.기본 클래스 속성은 코드에 레이아웃된 대로 정렬되지만 기본 클래스 속성 앞에 표시됩니다.
또한 JSON 속성을 알파벳 순으로 정렬하려는 이유를 알고 싶다면 원시 JSON 파일을 사용하는 것이 훨씬 더 쉽습니다. 특히 속성이 많은 클래스가 주문되어 있으면 더욱 편리합니다.
JsonProperty
Order
모든 클래스 속성에 속성을 부여하고, 그 후 독자적인 Contract Resolver를 만드는 것은 매우 간단합니다.
IContractResolver 인터페이스를 사용하면 JsonSerializer의 시리얼화 및 역직렬화 방법을 커스터마이즈할 수 있습니다.클래스에 Atribute를 배치하지 않고 NET 객체를 JSON으로 전송합니다.
다음과 같이 합니다.
private class SortedPropertiesContractResolver : DefaultContractResolver
{
// use a static instance for optimal performance
static SortedPropertiesContractResolver instance;
static SortedPropertiesContractResolver() { instance = new SortedPropertiesContractResolver(); }
public static SortedPropertiesContractResolver Instance { get { return instance; } }
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var properties = base.CreateProperties(type, memberSerialization);
if (properties != null)
return properties.OrderBy(p => p.UnderlyingName).ToList();
return properties;
}
}
구현:
var settings = new JsonSerializerSettings { ContractResolver = SortedPropertiesContractResolver.Instance };
var json = JsonConvert.SerializeObject(obj, Formatting.Indented, settings);
실제로 오브젝트는 이미 JObject이기 때문에 다음 솔루션을 사용했습니다.
public class SortedJObject : JObject
{
public SortedJObject(JObject other)
{
var pairs = new List<KeyValuePair<string, JToken>>();
foreach (var pair in other)
{
pairs.Add(pair);
}
pairs.OrderBy(p => p.Key).ForEach(pair => this[pair.Key] = pair.Value);
}
}
이렇게 사용합니다.
string serializedObj = JsonConvert.SerializeObject(new SortedJObject(dataObject));
에 의해 의 토큰 됩니다.JObject
인스턴스(instance)를 생성할 수 있습니다.진손이다.NET の net net net 。실가동에서는 사용하지 말아 주세요.
void SortProperties(JToken token)
{
var obj = token as JObject;
if (obj != null)
{
var props = typeof (JObject)
.GetField("_properties",
BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(obj);
var items = typeof (Collection<JToken>)
.GetField("items", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(props);
ArrayList.Adapter((IList) items)
.Sort(new ComparisonComparer(
(x, y) =>
{
var xProp = x as JProperty;
var yProp = y as JProperty;
return xProp != null && yProp != null
? string.Compare(xProp.Name, yProp.Name)
: 0;
}));
}
foreach (var child in token.Children())
{
SortProperties(child);
}
}
컨트롤할하면, 속성들이 됩니다.JsonConvert.SerializeObject()
출됩니니다다
하고 codecomblex에서 합니다. 냥가추 add add add add add add를 추가할 수 [JsonProperty(Order = 1)]
왜냐하면 수업 자체가 내 능력 밖이기 때문이다.
이 솔루션에서는 기본 클래스에 정의된 속성이 더 높은 우선 순위를 가져야 한다는 점도 고려합니다.
수 , 「방탄」이라고 않기 때문입니다.냐하면 、 에에에, 、MetaDataAttribute
올바른 질서를 유지하지만 효과가 있는 것 같습니다.제 사용 예에서는 자동 생성된 구성 파일에 대해 사람의 가독성만 유지하고 싶기 때문에 괜찮습니다.
public class PersonWithAge : Person
{
public int Age { get; set; }
}
public class Person
{
public string Name { get; set; }
}
public string GetJson()
{
var thequeen = new PersonWithAge { Name = "Elisabeth", Age = Int32.MaxValue };
var settings = new JsonSerializerSettings()
{
ContractResolver = new MetadataTokenContractResolver(),
};
return JsonConvert.SerializeObject(
thequeen, Newtonsoft.Json.Formatting.Indented, settings
);
}
public class MetadataTokenContractResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(
Type type, MemberSerialization memberSerialization)
{
var props = type
.GetProperties(BindingFlags.Instance
| BindingFlags.Public
| BindingFlags.NonPublic
).ToDictionary(k => k.Name, v =>
{
// first value: declaring type
var classIndex = 0;
var t = type;
while (t != v.DeclaringType)
{
classIndex++;
t = type.BaseType;
}
return Tuple.Create(classIndex, v.MetadataToken);
});
return base.CreateProperties(type, memberSerialization)
.OrderByDescending(p => props[p.PropertyName].Item1)
.ThenBy(p => props[p.PropertyName].Item1)
.ToList();
}
}
API를 순서 있는 필드와 함께 글로벌하게 설정하려면 Mattias Nordberg의 답변을 결합해 주십시오.
public class OrderedContractResolver : DefaultContractResolver
{
protected override System.Collections.Generic.IList<JsonProperty> CreateProperties(System.Type type, MemberSerialization memberSerialization)
{
return base.CreateProperties(type, memberSerialization).OrderBy(p => p.PropertyName).ToList();
}
}
제 답변은 다음과 같습니다.
ASP 강제 실행 방법항상 JSON을 반환하는 NET Web API를 선택하십시오.
갱신하다
방금 다운보트를 봤어요.이 방법은 아래 'Steve'의 답변을 참조하십시오.
원래의
는 ★★★★★★를 따라갔다.JsonConvert.SerializeObject(key)
을 통해 검출된 , 는 JsonSerializer로 검출되었습니다.InternalWriter.시리얼라이즈 리스트되어 「」를 경유하여 합니다.
for (int i = 0; i < values.Count; i++) { ...
여기서 values는 Import된 IList 파라미터입니다.
간단한 대답은...아니요, 필드가 JSON 문자열에 나열되는 순서를 설정할 수 있는 기본 제공 방법은 없습니다.
JSON 형식에는 필드 순서가 없으므로 순서를 정의하는 것은 의미가 없습니다.
{ id: 1, name: 'John' }
{ name: 'John', id: 1 }
다 엄밀하게 인스턴스를
언급URL : https://stackoverflow.com/questions/3330989/order-of-serialized-fields-using-json-net
'source' 카테고리의 다른 글
JSON 스키마의 "필수"와 "옵션"의 차이점은 무엇입니까? (0) | 2023.02.17 |
---|---|
파일과 함께 로컬로 로드된 모바일 WebView에서 CORS cookie 자격 정보:// (0) | 2023.02.17 |
Typescript-Interface/Type-definition을 스터브하는 방법 (0) | 2023.02.17 |
올바른 URL을 전달하려면 어떻게 해야 합니까?추가 앰퍼 및 문제 없이 JQuery 메서드에 대한 조치? (0) | 2023.02.17 |
Grid Builder Visual Composer에서 변수의 게시 ID 가져오기 (0) | 2023.02.17 |