2017-11-20 1 views
0

다른 사람들이 중복으로 표시했기 때문에이 질문을 다시 게시하겠습니다.하지만 혼동을 피하기 위해 자세한 내용을 설명합니다.가변 콘텐츠가 포함 된 C#을 사용하여 Json을 역 직렬화합니다.

저는 웹 애플리케이션이 도달 할 수있는 API를 일부 데이터를 생성 할 수 있습니다. 내 웹 애플 리케이션에서, 나는 (말) 제품의 목록을 볼 수 있습니다. 지금은 데이터베이스에 저장된 모든 제품을 반환하는 경로가 있습니다.

이제 웹 응용 프로그램이 복합 필터를 만들 수있는 기능을 추가하고 싶습니다. WebApp 또는 Postman과 함께 예를 들어, webapp에서 적용해야하는 모든 필터를 포함하는 "filters"라는 URlParam과 함께 "/ api/product"에 내 경로에 도달 할 수 있기를 원합니다.

이제 내 웹 응용 프로그램으로 돌아갑니다. (앵귤러로 빌드) 필터 트리처럼 만들 수있는 서비스가 있습니다 (아래 클래스 구조 참조). (그리고 네,이 구조는 개선 될 수있다)

enter image description here

아이디어는 내가 같이 필터를 만들 수 있다는 것입니다 : 내가 자신의 이름과 가격 gretter 이상으로 "foo는"이 모든 제품을 가져 오기하려면 15 $ :

let filter = new AndNode(); 
filter.Add(new LikeNode("name", "foo")); 
filter.Add(new GTNode("price", 15)); 
filter.generateJson(); 

이 JSON가 발생합니다 :

{ 
    "$and": [ 
     { 
      "$like": { "key": "name", "value": "foo" } 
     }, 
     { 
      "$gt": { "key": "price", "value": 15 } 
     } 
    ] 
} 

지금이 JSON은 1 개 요구 사항이 : 그것은 하나 이상의 홍보를 포함해서는 안됩니다 operat at는 1 단계입니다. 이것은 SQL 필터를 생성하는 데 사용되기 때문에 json은 EQ, LIKE, GT 또는 LT 노드 하나만 포함하거나 하나 이상의 필터가 AND 인 경우 첫 번째 노드에 하나의 노드 만 포함해야합니다./다음 레벨의 각 필터 사이의 논리적 "연결"을 정의하는 OR 노드.

{ 
    "$like": { "key": "name", "value": "foo" } 
} 

유효하며,이 SQL 문을 초래할 수 : 또한

SELECT * FROM products WHERE name LIKE "%foo%"; 

:

{ 
    "$and": [ 
     { 
      "$like": { "key": "name", "value": "foo" } 
     }, 
     { 
      "$gt": { "key": "price", "value": 15 } 
     } 
    ] 
} 

이 유효하고이 같이 발생할 수

은 그래서 의미가 있음이 있습니다 SQL 문 :

SELECT * FROM products WHERE name LIKE "%foo%" AND price > 15; 

그러나 :

SELECT * FROM products WHERE name LIKE "%foo%" price > 15 

마녀 때문에 누락 된 AND 또는 OR 키워드의 유효하지 않습니다 : 그것은이 SQL 문을 초래하기 때문에

{ 
    "$like": { "key": "name", "value": "foo" }, 
    "$eq": { "key": "price", "value": 5 }, 
} 

가 유효하지 않습니다.

내가 무엇을하고 싶은지 : 아름다운 세상에서 나는이 웹 응용 프로그램에서 json을 직렬화하고 유효한 URL 매개 변수 문자열로 변환하여 API (C#)로 보내고 싶습니다. JSON을 deserialize하여 웹 애플리케이션에서 사용한 것과 동일한 객체 구조를 얻습니다. 가격과 이름을 예로 들어 보겠습니다. LikeNode 클래스의 인스턴스 1 개와 GTNode 클래스의 인스턴스 1 개가 2 개의 객체를 포함하는 "child"멤버가있는 AndNode 클래스의 인스턴스를 갖고 싶습니다.

이 구현은 논쟁의 여지가 있지만, 지금 우리가 필요로하는 것입니다. 지금은

, 나는이 :

public class EQNode 
{ 
    [JsonProperty("key")] 
    public string key { get; set; } 

    [JsonProperty("value")] 
    public int value { get; set; } 
} 

public class LikeNode 
{ 
    [JsonProperty("key")] 
    public string key { get; set; } 

    [JsonProperty("value")] 
    public string value { get; set; } 
} 

public class GTNode 
{ 
    [JsonProperty("key")] 
    public string key { get; set; } 

    [JsonProperty("value")] 
    public int value { get; set; } 
} 

public class LTNode 
{ 
    [JsonProperty("key")] 
    public string key { get; set; } 

    [JsonProperty("value")] 
    public int value { get; set; } 
} 

public class OrNode 
{ 
    [JsonProperty("$eq")] 
    public EQNode eq { get; set; } 
} 

public class AndNode 
{ 
    [JsonProperty("$eq")] 
    public EQNode eq { get; set; } 

    [JsonProperty("$like")] 
    public LikeNode like { get; set; } 

    [JsonProperty("$gt")] 
    public GTNode gt { get; set; } 

    [JsonProperty("$lt")] 
    public LTNode lt { get; set; } 

    [JsonProperty("$or")] 
    public List<OrNode> or { get; set; } 

    [JsonProperty("$and")] 
    public List<OrNode> and { get; set; } 
} 

public class RootObject 
{ 
    [JsonProperty("$and")] 
    public List<AndNode> and { get; set; } 

    [JsonProperty("$or")] 
    public List<OrNode> or { get; set; } 

    [JsonProperty("$eq")] 
    public EQNode eq { get; set; } 

    [JsonProperty("$like")] 
    public LikeNode like { get; set; } 

    [JsonProperty("$gt")] 
    public GTNode gt { get; set; } 

    [JsonProperty("$lt")] 
    public LTNode lt { get; set; } 
} 

이 비주얼 스튜디오의 "과거 특별한"기능에 의해 생성 된 (그리고 나는 내 JSON의 이름과 일치하는 모든 JsonProperty의 장식을 추가). 그것은 작동하지만, 이것은 내가 예상했던 것이 아닙니다.

먼저 웹 애플리케이션 구조 (상속 포함)에서 가장 가까운 구조를 갖고 싶습니다. 둘째,이 생성 된 코드가 $ eq, $ gt, $ lt, $ like, $ or 또는 $ 및 node를 루트 객체에 포함 할 수 있다는 사실을 처리하는 방식이 좋지 않습니다. 믿을 수 없습니다. 우리가 사용하는 경우 : (이 예 목적을위한 존재하지 않거나 잘못 사용되는 사용되는 일부 장식, 이것은 단지 데모입니다 주)

public class RootObject { 
    public FilterNode root; 
} 

public class FilterNode { 
} 

public class ConjunctionNode: FilterNode { 
    public FilterNode[] childs 
} 

[JsonObject("$and")] 
public class AndNode: ConjunctionNode { 
} 

[JsonObject("$or")] 
public class OrNode: ConjunctionNode { 
} 

[JsonObject("$like")] 
public class LikeNode: FilterNode { 
    public string key; 
    public string value; 
} 

[JsonObject("$eq")] 
public class EQNode: FilterNode { 
    public string key; 
    public string value; 
} 

[JsonObject("$gt")] 
public class GTNode: FilterNode { 
    public string key; 
    public string value; 
} 

[JsonObject("$lt")] 
public class LTNode: FilterNode { 
    public string key; 
    public string value; 
} 

그래서, : 그런 깨끗한 구조를 가질 수있는 방법은 없습니다 샘플 JSON은 :

{ 
    "$and": [ 
     { 
      "$like": { "key": "name", "value": "foo" } 
     }, 
     { 
      "$gt": { "key": "price", "value": 15 } 
     } 
    ] 
} 

내가 사용할 수 있습니다

RootObject obj = JsonConvert.DeserializeObject<RootObject>(filters); 

RootObject의 "root"멤버를 AndNode의 인스턴스로 사용합니다. 이 AndNode에는이 하위 배열의 LikeNode 인스턴스와 GTNode 인스턴스 인 두 개의 개체가 포함됩니다.

이 작업을 수행 할 수 있습니까?

+0

초기 질문에 게시 된 답변에 어떤 문제가 있습니까? – Izzy

+0

원래 게시물은 덜 자세했습니다. 그러나 거기에는 다음과 같은 응답이 있습니다. "과거의 특별한 특징"을 사용하는 것이 좋은 충고 였고, 다른 대답은 나에게 더 많은 것을 묻고있었습니다. 그래서 지금 나는 이것을 풀기 위해 대답했다. –

+0

새 질문을 게시하는 대신 초기 질문을 업데이트해야합니다. 또한 @ angsuman-ray는 상세한 JSON을 요청하며, 그 외형에 의해 당신은 그들에게 돌아 가지 않았다. – Izzy

답변

1

나는 당신의 문제를 자세히 조사했다. 비 직렬화하려는 객체 모델에 결함이 있습니다. 또한 키가 계속 변경 될 수 있으므로 직접 직렬화를 사용할 수 없습니다. 따라서 json 단계를 거쳐 사전이나 원하는 데이터 유형을 찾아서 저장해야합니다. 여기

는 제안 된 객체 클래스입니다 :
using System.Collections.Generic; 

namespace ConsoleApp1 
{ 
    public class RootObject 
    { 
     public RootObject() 
     { 
      ConjunctionNode = new List<ConjunctionNode>(); 
     } 

     public List<ConjunctionNode> ConjunctionNode { get; set; } 
    } 

    public class FilterNode 
    { 
     public string Key { get; set; } 
     public string Value { get; set; } 
    } 

    public class ConjunctionNode 
    { 
     public LikeNode Like { get; set; } 
     public EQNode Eq { get; set; } 
     public GTNode Gt { get; set; } 
     public LTNode Lt { get; set; } 
    } 

    public class AndNode : ConjunctionNode 
    { 
    } 

    public class OrNode : ConjunctionNode 
    { 
    } 

    public class LikeNode : FilterNode 
    { 
    } 

    public class EQNode : FilterNode 
    { 
    } 

    public class GTNode : FilterNode 
    { 
    } 

    public class LTNode : FilterNode 
    { 
    } 
} 

이 객체가 어떻게 만들어 지는지를 참조하십시오. 이제 json 단계를 단계별로 읽고 분기점을 작성한 다음 저장하고 읽거나 읽을 수 있어야합니다.

이제 데이터를 얻으려고 시작 했으므로이 방법을 사용하면 한 번 시도 할 수 있습니다. 어려움을 겪는다면 자유롭게 돌아와서 더 많은 작업을하거나 다른 해결 방법을 찾아 낼 수 있습니다.

using Newtonsoft.Json; 
using System.IO; 

namespace ConsoleApp1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      RootObject rootObject = new RootObject(); 
      string json = @"{ ""$and"": [ { ""$like"": { ""key"": ""name"", ""value"": ""foo"" } }, {""$gt"": { ""key"": ""price"", ""value"": 15 } } ] } "; 
      //var rootObject = JsonConvert.DeserializeObject<RootObject>(json); 


      using (var reader = new JsonTextReader(new StringReader(json))) 
      { 
       while (reader.Read()) 
       { 
        //Console.WriteLine("{0} - {1} - {2}", reader.TokenType, reader.ValueType, reader.Value); 
        if (reader.TokenType.ToString() == "PropertyName") 
        { 
         //Console.WriteLine("Hi"); 
         CreateConjunctionNode(reader, rootObject); 
         //CreateFilterNode(reader, rootObject); 
         //Console.WriteLine(reader.Value); 
        } 
       } 
      } 
     } 

     private static void CreateFilterNode(JsonTextReader reader, RootObject rootObject) 
     { 
      if (reader.Value.ToString() == "$like") 
      { 
       LikeNode likeNode = new LikeNode(); 
      } 
      else if (reader.Value.ToString() == "$gt") 
      { 
       GTNode gTNode = new GTNode(); 
      } 
      else if (reader.Value.ToString() == "$lt") 
      { 
       LTNode lTNode = new LTNode(); 
      } 
      else if (reader.Value.ToString() == "$eq") 
      { 
       EQNode eQNode = new EQNode(); 
      } 
     } 

     private static void CreateConjunctionNode(JsonTextReader reader, RootObject rootObject) 
     { 
      if (reader.Value.ToString() == "$and") 
      { 
       rootObject.ConjunctionNode.Add(new AndNode()); 
      } 
      else if (reader.Value.ToString() == "$or") 
      { 
       rootObject.ConjunctionNode.Add(new OrNode()); 
      } 
     } 
    } 
} 
+0

안녕하세요, 귀하의 답변에 감사드립니다. "수동"직렬화를 피하려고했지만 다른 방법으로는 수행 할 수 없으므로이 작업을 수행 할 것입니다. 이렇게하면 원하는 객체 구조에서 내 객체가 deserialize됩니다. 정확히 내가 필요로하는 최종 결과. 감사 ! –

+0

좋습니다. 항상 느슨하게 사물을 연결하십시오. 모듈화되고 재사용 가능한 것들을 만드십시오. – inthevortex

관련 문제