2016-06-06 6 views
0

Json.net (JsonConvert.SerializeXNode)을 사용하여 xml을 json으로 변환하려고합니다.어쨌든 json.net을 사용하여 xson 배열을 json으로 변환하는 동안 추가 "객체 노드"생성을 막을 수 있습니까?

일종의 스키마 (xsd)를 사용하지 않으면 xml과 json을 변환하려고 할 때 문제가 발생합니다. xml 컬렉션과 단일 요소의 차이를 실제로 식별 할 수 없기 때문입니다 일반 물체에.

예 : 아무도 드라이버는 하나의 객체 모음입니다 시리얼 라이저를 알 수 없기 때문에

"Drivers":{ "Driver": { "Name": "MyName" } } 

하고 그냥 일반 객체의 생각 :

<Drivers> 
    <Driver> 
    <Name>MyName</Name> 
    </Driver> 
</Drivers> 

가로 변환됩니다.

Json.netjson:Array='true' 태그를 사용하여이 문제를 해결할 수 있습니다. 당신이 배열에 태그를 할 때

모든 것이 잘 작동하지만, 추가 중간 오브젝트 (드라이버)를 작성 :

"Drivers": [{"Driver":{"Name": "MyName"}}] 

이제 이해가이 노드를 만든 이유를,하지만 난 할 수있는 방법을 찾기 위해 노력하고있어 그 생성을 우회하십시오. 이 결과를 얻고 싶습니다.

"Drivers": [{"Name": "MyName"}] 

누구나 이런 식으로 할 생각이 있습니까?

+0

http://stackoverflow.com/questions/814001/ convert-json-to-xml-or-xml-to-json –

+0

Amir, 아마 시도해 보았지만 언급 한 메소드의 문서는'omitRootObject'라는 매개 변수를 보여줍니다 - 도움이 될까요? – Veverke

+0

@StephenBrickner - 잠시 전에 읽은 다음 다시 읽었습니다. 나는 그들의 관련 솔루션을 찾지 못했습니다. 내가 놓친 게 있니? –

답변

1

Json.NET 자동 직렬화 컬렉션을 변환 할 것이다 outer container element (예를 들면, 부착 [XmlArray] 생성 한) 단일 JSON 배열. 대신 XML을 LINQ-to-XML으로 사전 처리하거나 LINQ-to-JSON으로 사후 처리하여 원하지 않는 중첩 수준을 수동으로 평평하게 조정해야합니다.

json:Array='true' 속성을 추가하기 위해 XML을 이미 사전 처리 중이므로 일부 전처리를 추가하는 것이 가장 간단합니다. 먼저 다음 확장 메서드 소개 :

var xnode = XDocument.Parse(xml); 
xnode.Descendants("Drivers").FlattenCollection(); 
var json = JsonConvert.SerializeXNode(xnode, Formatting.Indented, true); 

을 그리고 당신이 원하는 JSON을 얻을 :

public static class XNodeExtensions 
{ 
    /// <summary> 
    /// Flatten a two-level collection with an outer container element to a one-level collection 
    /// in preparation for conversion to JSON using Json.NET 
    /// </summary> 
    /// <param name="parents">The outer container elements.</param> 
    /// <param name="childName">The inner element name. If null, flatten all children.</param> 
    /// <param name="newChildName">The new element name. If null, use the parent name.</param> 
    public static void FlattenCollection(this IEnumerable<XElement> parents, XName childName = null, XName newChildName = null) 
    { 
     if (parents == null) 
      throw new ArgumentNullException(); 

     XNamespace json = @"http://james.newtonking.com/projects/json"; 
     XName isArray = json + "Array"; 

     foreach (var parent in parents.ToList()) 
     { 
      if (parent.Parent == null) 
       continue; // Removed or root 
      foreach (var child in (childName == null ? parent.Elements() : parent.Elements(childName)).ToList()) 
      { 
       child.Remove(); 
       child.Name = newChildName ?? parent.Name; 
       child.Add(new XAttribute(isArray, true)); 
       parent.Parent.Add(child); 
      } 
      if (!parent.HasElements) 
       parent.Remove(); 
     } 
    } 
} 

을 이제 할 수 있습니다. 샘플 fiddle.

XML 문서에는 정확하게 하나의 루트 노드가 있어야하므로 <Drivers>root element이 될 수 없습니다.

+1

답변 해 주셔서 감사합니다. 마지막 계획으로 XML을 평평하게 만드는 것에 대해 생각했고, 더 좋은 방법을 찾지 못했기 때문에 그것을 할 것입니다. 구현 방법에 대해서는 필자의 경우에 맞게 약간 구현했습니다. 응답 해 주셔서 감사합니다. –

0

omitRootObject 플래그가 true로 설정된 아래 예제를 실행하면됩니다. false로 설정하면 실제로 상위 Driver 노드를 얻습니다.이 노드는 제거하려고합니다.

XmlDocument xmlDoc = new XmlDocument(); 
    xmlDoc.LoadXml(@"<Drivers> 
        <Driver> 
        <Name>MyName</Name> 
        </Driver> 
       </Drivers>"); 


    var result = JsonConvert.SerializeXmlNode(xmlDoc.FirstChild, Newtonsoft.Json.Formatting.Indented, true); 

    Console.WriteLine(result); 

출력 :

enter image description here

false로 omitRootNode를 설정하고 당신이 제거하려고하는 루트 노드를 얻을 것이다.

enter image description here

+0

우선, 드라이버는 내 유일한 노드가 아닙니다. 나는 큰 xml을 가지고 있고 그것의 일부이다. 둘째로, 나는 "드라이버"처럼 보이는 응답이 필요하다 : [{ ""Name ":"MyName "}]'. 시도해 줘서 고마워. –

0

평평하게 다르게 구현했습니다. dbc의 대답을 받아 들였습니다. 질문에 답을 해 주었기 때문에 누군가가이 문제를 해결하고 필요로 할 때를 대비해 구현했습니다.

public static class XNodeExtensions 
{ 
    public static void FlattenCollection(this XElement parent) 
    { 
     if (parent == null || parent.Parent == null) 
      throw new ArgumentNullException(); 

     if (parent.Elements().Count() == 0) 
      return; 

     XNamespace json = @"http://james.newtonking.com/projects/json"; 
     XName isArray = json + "Array"; 

     foreach (var child in parent.Elements().ToList()) 
     { 
      child.Remove(); 
      child.Name = parent.Name; 
      child.Add(new XAttribute(isArray, true)); 
      parent.Parent.Add(child); 
     } 

     parent.Remove(); 
    } 
}