【问题标题】:Parsing Firebase JSON F#解析 Firebase JSON F#
【发布时间】:2018-01-21 16:31:58
【问题描述】:

我正在尝试将以下 Firebase JSON 转换为可以在 F# 中解析的内容:

{  
   "listings":{  
      "-L0pJmU9yj4hAocHjnrB":{  
         "listing_id":"-L0pJmU9yj4hAocHjnrB",
         "location":"Edinburgh",
         "messages":{  
            "SWs56OIGzMdiCjSXahzDQX8zve92":{  
               "-L3ELSSzZPRdjCRcFTrb":{  
                  "senderId":"SWs56OIGzMdiCjSXahzDQX8zve92",
                  "senderName":"alberto",
                  "text":"Hi"
               },
               "-L3EN1NW5hHWBTEGC9ve":{  
                  "senderId":"YMM45tgFFvYB7rx9PhC2TE5eW6D2",
                  "senderName":"David",
                  "text":"Hey"
               }
            }
         }
      },
      "-L19C5OjcDSjMi4-oha-":{  
         "listing_id":"-L19C5OjcDSjMi4-oha-",
         "location":"Edinburgh"
      },
      "-L19CJrzEpChO_W14YkC":{  
         "listing_id":"-L19CJrzEpChO_W14YkC",
         "location":"Edinburgh",
         "messages":{  
            "Rp7ytJdEvZeMFgpLqeCSzkSeTyf1":{  
               "-L19V4QpPMCMwGcNaQBG":{  
                  "senderId":"Rp7ytJdEvZeMFgpLqeCSzkSeTyf1",
                  "senderName":"Albert",
                  "text":"Hey there"
               },
               "-L19r0osoet4f9SjBGE7":{  
                  "senderId":"YMM45tgFFvYB7rx9PhC2TE5eW6D2",
                  "senderName":"David",
                  "text":"Hi"
               },
               "-L3ELGAbcOjdJsHRtnAe":{  
                  "senderId":"YMM45tgFFvYB7rx9PhC2TE5eW6D2",
                  "senderName":"David",
                  "text":"Icvjv"
               }
            }
         }
      },
      "-L19ChjPjX1DnfQb28AW":{  
         "listing_id":"-L19ChjPjX1DnfQb28AW",
         "location":"Edinburgh",
         "messages":{  
            "879dUqGuiXSd95QHzfhbSs05IZn2":{  
               "-L1i6c7sGf3BcF2cCSCu":{  
                  "senderId":"879dUqGuiXSd95QHzfhbSs05IZn2",
                  "senderName":"Alberto",
                  "text":"Hello"
               }
            },
            "Rp7ytJdEvZeMFgpLqeCSzkSeTyf1":{  
               "-L19FGCMuQACjYKCFEwV":{  
                  "senderId":"Rp7ytJdEvZeMFgpLqeCSzkSeTyf1",
                  "senderName":"Albert",
                  "text":"Hey"
               },
               "-L19T_v2Utxhu1mGhz7-":{  
                  "senderId":"YMM45tgFFvYB7rx9PhC2TE5eW6D2",
                  "senderName":"David",
                  "text":"Hi"
               },
               "-L19TbhActGmga4f47Mz":{  
                  "senderId":"Rp7ytJdEvZeMFgpLqeCSzkSeTyf1",
                  "senderName":"Albert",
                  "text":"How are you"
               }
            }
         }
      },
      "-L19Cz1abm1o-JCbiAnN":{  
         "listing_id":"-L19Cz1abm1o-JCbiAnN",
         "location":"Edinburgh"
      },
      "-L19DMdFx2pXj9-EKCq2":{  
         "listing_id":"-L19DMdFx2pXj9-EKCq2",
         "location":"Edinburgh"
      },
      "-L19DV67WjguozFE_4dM":{  
         "listing_id":"-L19DV67WjguozFE_4dM",
         "location":"Edinburgh"
      }
   }
}

这里的问题是,像第二行中的L0pJmU9yj4hAocHjnrB这样的条目以及随后的类似条目是在Firebase中创建的自动生成的时间戳ID,并且它们没有对应的名称,例如:"listing_id":"-L0pJmU9yj4hAocHjnrB",因此我这样做了不知道如何设置我的 F# 记录以正确解析此 JSON。

我的尝试如下所示:

type MessageContent = 
    { senderId: string
      senderName: string
      text: string; }

type Message =
     { timestampId : string
       chatMessages : MessageContent;}

type Chat = 
    { chatPartnerId : string 
      Messages : Message array option;}

type ListingContent = 
    { from : string
      landlord_id : string
      listing_id : string
      location : string
      name : string
      pic_1_url : string
      pic_2_url : string
      pic_3_url : string
      pic_4_url : string
      pic_5_url : string
      messages : Chat array option
      postcode : string
      price_per_night : int
      to_date : string;
    }

type Listing =
     { timestampId : string
       listingcontent : ListingContent option;}

type City = 
    { city : string
      listings : Listing array option
    }

type AllListings = 
    { cities : City array;}

type SearchSettings = 
    { from : string
      location : string
      max_price : decimal
      min_price : decimal
      to_date : string;}

type MatchContent = 
    { id : string
      location : string;}

type Match = 
    {timestampId : string
     matchContent : MatchContent;}

type DeclinedContent = 
    { id : string;
      }

type Declined = 
    {timestampId : string
     declinedContent : DeclinedContent;}

type ListingUserContent = 
    { listing_id : string
      location : string
      messages : Chat array option;
    }

type ListingUser = 
    {timestampId : string
     listingUser : ListingUserContent;}

type UserContent = 
    { declined: Declined option
      matches : Match option
      search_settings : SearchSettings option
      listings : ListingUser option;
    }

我使用以下代码进行解析:

    let myCallbackGetChats (reader:IO.StreamReader) url = 
    let html = reader.ReadToEnd()
    let reader = new JsonTextReader(reader);
    let serializer = JsonSerializer.Create(JsonSerializerSettings(Converters = [| Types.OptionConverter() |]))
    use stringReader = new StringReader(html)
    use jsonReader = new JsonTextReader(stringReader)
    let listings_json = serializer.Deserialize<Types.UserContent>(jsonReader)
    printfn "%A" listings_json

这会产生以下输出:

    {declined = null;
 matches = null;
 search_settings = null;
 listings = Some {listing_id = null;
                  location = null;
                  messages = null;};}

我们可以看到第一个listings 标记已正确反序列化,但是一旦它看到L0pJmU9yj4hAocHjnrB,它就不知道那是什么,其余的解析就会失败。我该如何解决这个问题?

【问题讨论】:

    标签: json firebase firebase-realtime-database f# json.net


    【解决方案1】:

    您可以使用以下 F# 类型反序列化您的 JSON:

    type MessageContent = 
        { senderId: string
          senderName: string
          text: string; 
        }
    
    type ListingContent = 
        { listing_id : string
          location : string
          messages : Map<string, Map<string, MessageContent>>
          // Add other members as required
        }
    
    type UserContent =
        { listings: Map<string, ListingContent>
          // Add other members as required
        }
    

    还有下面这行代码:

    let listings_json = JsonConvert.DeserializeObject<UserContent>(inputJson)
    

    注意事项:

    • "listing" 对象由变量属性名称及其值的固定架构组成。如Serialization Guide: Dictionaries and Hashtables 中所述,此类对象可以映射到.Net 字典。在这种情况下,我选择了 F# Collections.Map&lt;'Key,'Value&gt; 类,特别是 Map&lt;string, ListingContent&gt;

    • 同样,"messages" 对象由变量属性名称组成,其值是具有变量属性名称的对象的嵌套级别,因此可以用 Map&lt;string, Map&lt;string, MessageContent&gt;&gt; 表示。

    • 我通过删除示例 JSON 中实际不存在的成员来简化 UserContentListingContent 类型。您可以根据需要重新添加它们。

    • 由于 Json.NET 内置了对字典的支持,因此此解决方案不需要自定义 JsonConverter

    工作示例F# fiddle

    【讨论】:

      猜你喜欢
      • 2011-04-03
      • 2018-06-28
      • 2021-11-23
      • 2018-08-12
      • 1970-01-01
      • 2023-03-21
      • 1970-01-01
      • 1970-01-01
      • 2018-01-30
      相关资源
      最近更新 更多